summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/_copyright/Makefile.am2
-rw-r--r--src/_copyright/Makefile.in5
-rw-r--r--src/charon/Makefile.am22
-rw-r--r--src/charon/Makefile.in147
-rw-r--r--src/charon/bus/bus.c335
-rw-r--r--src/charon/bus/bus.h376
-rw-r--r--src/charon/bus/listeners/file_logger.c45
-rw-r--r--src/charon/bus/listeners/file_logger.h14
-rw-r--r--src/charon/bus/listeners/sys_logger.c39
-rw-r--r--src/charon/bus/listeners/sys_logger.h16
-rw-r--r--src/charon/config/backend_manager.c19
-rw-r--r--src/charon/config/child_cfg.c99
-rw-r--r--src/charon/config/child_cfg.h41
-rw-r--r--src/charon/config/peer_cfg.c60
-rw-r--r--src/charon/config/proposal.c2
-rw-r--r--src/charon/config/traffic_selector.c109
-rw-r--r--src/charon/config/traffic_selector.h28
-rw-r--r--src/charon/control/controller.c505
-rw-r--r--src/charon/control/controller.h20
-rw-r--r--src/charon/credentials/credential_manager.c49
-rw-r--r--src/charon/credentials/sets/cert_cache.c28
-rw-r--r--src/charon/daemon.c257
-rw-r--r--src/charon/daemon.h17
-rw-r--r--src/charon/encoding/payloads/payload.c20
-rw-r--r--src/charon/encoding/payloads/traffic_selector_substructure.c6
-rw-r--r--src/charon/kernel/kernel_interface.c122
-rw-r--r--src/charon/kernel/kernel_interface.h79
-rw-r--r--src/charon/kernel/kernel_ipsec.c9
-rw-r--r--src/charon/kernel/kernel_ipsec.h73
-rw-r--r--src/charon/network/sender.c49
-rw-r--r--src/charon/network/socket-raw.c136
-rw-r--r--src/charon/network/socket.c109
-rw-r--r--src/charon/network/socket.h24
-rw-r--r--src/charon/plugins/eap_aka/eap_aka.c3
-rw-r--r--src/charon/plugins/kernel_klips/Makefile.am10
-rw-r--r--src/charon/plugins/kernel_klips/Makefile.in501
-rw-r--r--src/charon/plugins/kernel_klips/kernel_klips_ipsec.c2659
-rw-r--r--src/charon/plugins/kernel_klips/kernel_klips_ipsec.h48
-rw-r--r--src/charon/plugins/kernel_klips/kernel_klips_plugin.c58
-rw-r--r--src/charon/plugins/kernel_klips/kernel_klips_plugin.h49
-rw-r--r--src/charon/plugins/kernel_klips/pfkeyv2.h322
-rw-r--r--src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c864
-rw-r--r--src/charon/plugins/kernel_netlink/kernel_netlink_net.c269
-rw-r--r--src/charon/plugins/kernel_netlink/kernel_netlink_shared.c20
-rw-r--r--src/charon/plugins/kernel_netlink/kernel_netlink_shared.h12
-rw-r--r--src/charon/plugins/kernel_pfkey/Makefile.am10
-rw-r--r--src/charon/plugins/kernel_pfkey/Makefile.in501
-rw-r--r--src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c1991
-rw-r--r--src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.h48
-rw-r--r--src/charon/plugins/kernel_pfkey/kernel_pfkey_plugin.c58
-rw-r--r--src/charon/plugins/kernel_pfkey/kernel_pfkey_plugin.h49
-rw-r--r--src/charon/plugins/load_tester/Makefile.am16
-rw-r--r--src/charon/plugins/load_tester/Makefile.in509
-rw-r--r--src/charon/plugins/load_tester/load_tester_config.c143
-rw-r--r--src/charon/plugins/load_tester/load_tester_config.h53
-rw-r--r--src/charon/plugins/load_tester/load_tester_creds.c236
-rw-r--r--src/charon/plugins/load_tester/load_tester_creds.h53
-rw-r--r--src/charon/plugins/load_tester/load_tester_ipsec.c165
-rw-r--r--src/charon/plugins/load_tester/load_tester_ipsec.h48
-rw-r--r--src/charon/plugins/load_tester/load_tester_listener.c75
-rw-r--r--src/charon/plugins/load_tester/load_tester_listener.h53
-rw-r--r--src/charon/plugins/load_tester/load_tester_plugin.c175
-rw-r--r--src/charon/plugins/load_tester/load_tester_plugin.h51
-rw-r--r--src/charon/plugins/medcli/medcli_listener.c76
-rw-r--r--src/charon/plugins/medcli/medcli_listener.h2
-rw-r--r--src/charon/plugins/nm/Makefile.am2
-rw-r--r--src/charon/plugins/nm/Makefile.in2
-rw-r--r--src/charon/plugins/nm/nm_creds.c38
-rw-r--r--src/charon/plugins/nm/nm_service.c154
-rw-r--r--src/charon/plugins/smp/smp.c18
-rw-r--r--src/charon/plugins/sql/pool.c14
-rw-r--r--src/charon/plugins/sql/sql_attribute.c22
-rw-r--r--src/charon/plugins/sql/sql_logger.c13
-rw-r--r--src/charon/plugins/sql/sql_logger.h2
-rw-r--r--src/charon/plugins/stroke/stroke_ca.c30
-rw-r--r--src/charon/plugins/stroke/stroke_config.c4
-rw-r--r--src/charon/plugins/stroke/stroke_control.c4
-rw-r--r--src/charon/plugins/stroke/stroke_cred.c37
-rw-r--r--src/charon/plugins/stroke/stroke_list.c104
-rw-r--r--src/charon/plugins/stroke/stroke_socket.c36
-rw-r--r--src/charon/plugins/unit_tester/tests/test_pool.c1
-rw-r--r--src/charon/plugins/updown/Makefile.am12
-rw-r--r--src/charon/plugins/updown/Makefile.in501
-rw-r--r--src/charon/plugins/updown/updown_listener.c320
-rw-r--r--src/charon/plugins/updown/updown_listener.h51
-rw-r--r--src/charon/plugins/updown/updown_plugin.c65
-rw-r--r--src/charon/plugins/updown/updown_plugin.h49
-rw-r--r--src/charon/processing/jobs/acquire_job.c31
-rw-r--r--src/charon/processing/jobs/acquire_job.h9
-rw-r--r--src/charon/processing/jobs/callback_job.c30
-rw-r--r--src/charon/processing/jobs/initiate_mediation_job.c82
-rw-r--r--src/charon/processing/jobs/migrate_job.c152
-rw-r--r--src/charon/processing/jobs/migrate_job.h65
-rw-r--r--src/charon/processing/processor.c68
-rw-r--r--src/charon/sa/authenticators/eap/eap_manager.c22
-rw-r--r--src/charon/sa/authenticators/eap_authenticator.c57
-rw-r--r--src/charon/sa/authenticators/psk_authenticator.c97
-rw-r--r--src/charon/sa/authenticators/pubkey_authenticator.c47
-rw-r--r--src/charon/sa/child_sa.c1112
-rw-r--r--src/charon/sa/child_sa.h138
-rw-r--r--src/charon/sa/connect_manager.c72
-rw-r--r--src/charon/sa/ike_sa.c694
-rw-r--r--src/charon/sa/ike_sa.h143
-rw-r--r--src/charon/sa/ike_sa_manager.c97
-rw-r--r--src/charon/sa/ike_sa_manager.h8
-rw-r--r--src/charon/sa/keymat.c568
-rw-r--r--src/charon/sa/keymat.h154
-rw-r--r--src/charon/sa/mediation_manager.c34
-rw-r--r--src/charon/sa/task_manager.c39
-rw-r--r--src/charon/sa/tasks/child_create.c223
-rw-r--r--src/charon/sa/tasks/child_delete.c21
-rw-r--r--src/charon/sa/tasks/child_rekey.c28
-rw-r--r--src/charon/sa/tasks/ike_auth.c108
-rw-r--r--src/charon/sa/tasks/ike_auth_lifetime.c7
-rw-r--r--src/charon/sa/tasks/ike_delete.c41
-rw-r--r--src/charon/sa/tasks/ike_init.c160
-rw-r--r--src/charon/sa/tasks/ike_me.c10
-rw-r--r--src/charon/sa/tasks/ike_mobike.c16
-rw-r--r--src/charon/sa/tasks/ike_reauth.c11
-rw-r--r--src/charon/sa/tasks/ike_rekey.c65
-rw-r--r--src/charon/sa/tasks/task.c25
-rw-r--r--src/dumm/Makefile.am4
-rw-r--r--src/dumm/Makefile.in8
-rw-r--r--src/dumm/dumm.c17
-rw-r--r--src/dumm/ext/dumm.c19
-rw-r--r--src/dumm/guest.c15
-rw-r--r--src/dumm/guest.h14
-rw-r--r--src/dumm/iface.c12
-rw-r--r--src/dumm/main.c1
-rw-r--r--src/dumm/mconsole.c14
-rw-r--r--src/dumm/mconsole.h2
-rw-r--r--src/include/linux/ipsec.h5
-rw-r--r--src/include/linux/pfkeyv2.h20
-rw-r--r--src/include/linux/xfrm.h10
-rw-r--r--src/libfreeswan/freeswan.h3
-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
-rw-r--r--src/pluto/ac.c4
-rw-r--r--src/pluto/ca.c4
-rw-r--r--src/pluto/constants.c4
-rw-r--r--src/pluto/constants.h7
-rw-r--r--src/pluto/crl.c4
-rw-r--r--src/pluto/defs.c11
-rw-r--r--src/pluto/fetch.c8
-rw-r--r--src/pluto/vendor.c5
-rw-r--r--src/pluto/vendor.h3
-rw-r--r--src/scepclient/scep.c2
-rw-r--r--src/starter/Makefile.am20
-rw-r--r--src/starter/Makefile.in25
-rw-r--r--src/starter/args.c3
-rw-r--r--src/starter/confread.c31
-rw-r--r--src/starter/confread.h4
-rw-r--r--src/starter/files.h5
-rw-r--r--src/starter/invokepluto.c6
-rw-r--r--src/starter/ipsec.conf.522
-rw-r--r--src/starter/keywords.c7
-rw-r--r--src/starter/keywords.h3
-rw-r--r--src/starter/keywords.txt3
-rw-r--r--src/starter/klips.c82
-rw-r--r--src/starter/klips.h24
-rw-r--r--src/starter/lex.yy.c43
-rw-r--r--src/starter/netkey.c22
-rw-r--r--src/starter/parser.l3
-rw-r--r--src/starter/starter.c13
-rw-r--r--src/starter/starterstroke.c36
-rw-r--r--src/stroke/Makefile.am2
-rw-r--r--src/stroke/Makefile.in2
-rw-r--r--src/stroke/stroke_msg.h5
-rw-r--r--src/whack/whack.c4
199 files changed, 15688 insertions, 4685 deletions
diff --git a/src/_copyright/Makefile.am b/src/_copyright/Makefile.am
index d8dcfb3f1..00d5fb2ff 100644
--- a/src/_copyright/Makefile.am
+++ b/src/_copyright/Makefile.am
@@ -3,4 +3,4 @@ _copyright_SOURCES = _copyright.c
dist_man8_MANS = _copyright.8
INCLUDES = -I$(top_srcdir)/src/libfreeswan
-_copyright_LDADD = $(top_srcdir)/src/libfreeswan/libfreeswan.a
+_copyright_LDADD = $(top_builddir)/src/libfreeswan/libfreeswan.a
diff --git a/src/_copyright/Makefile.in b/src/_copyright/Makefile.in
index a8f14689a..031b0846d 100644
--- a/src/_copyright/Makefile.in
+++ b/src/_copyright/Makefile.in
@@ -47,7 +47,8 @@ ipsecPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(ipsec_PROGRAMS)
am__copyright_OBJECTS = _copyright.$(OBJEXT)
_copyright_OBJECTS = $(am__copyright_OBJECTS)
-_copyright_DEPENDENCIES = $(top_srcdir)/src/libfreeswan/libfreeswan.a
+_copyright_DEPENDENCIES = \
+ $(top_builddir)/src/libfreeswan/libfreeswan.a
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -207,7 +208,7 @@ xml_LIBS = @xml_LIBS@
_copyright_SOURCES = _copyright.c
dist_man8_MANS = _copyright.8
INCLUDES = -I$(top_srcdir)/src/libfreeswan
-_copyright_LDADD = $(top_srcdir)/src/libfreeswan/libfreeswan.a
+_copyright_LDADD = $(top_builddir)/src/libfreeswan/libfreeswan.a
all: all-am
.SUFFIXES:
diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am
index c9f63ac9d..e3d3e8e14 100644
--- a/src/charon/Makefile.am
+++ b/src/charon/Makefile.am
@@ -52,6 +52,7 @@ processing/jobs/acquire_job.c processing/jobs/acquire_job.h \
processing/jobs/callback_job.c processing/jobs/callback_job.h \
processing/jobs/delete_child_sa_job.c processing/jobs/delete_child_sa_job.h \
processing/jobs/delete_ike_sa_job.c processing/jobs/delete_ike_sa_job.h \
+processing/jobs/migrate_job.c processing/jobs/migrate_job.h \
processing/jobs/process_message_job.c processing/jobs/process_message_job.h \
processing/jobs/rekey_child_sa_job.c processing/jobs/rekey_child_sa_job.h \
processing/jobs/rekey_ike_sa_job.c processing/jobs/rekey_ike_sa_job.h \
@@ -74,6 +75,7 @@ sa/ike_sa.c sa/ike_sa.h \
sa/ike_sa_id.c sa/ike_sa_id.h \
sa/ike_sa_manager.c sa/ike_sa_manager.h \
sa/task_manager.c sa/task_manager.h \
+sa/keymat.c sa/keymat.h \
sa/tasks/child_create.c sa/tasks/child_create.h \
sa/tasks/child_delete.c sa/tasks/child_delete.h \
sa/tasks/child_rekey.c sa/tasks/child_rekey.h \
@@ -144,6 +146,21 @@ endif
SUBDIRS = .
PLUGINS = ${libstrongswan_plugins}
+if USE_LOAD_TESTS
+ SUBDIRS += plugins/load_tester
+ PLUGINS += load-tester
+endif
+
+if USE_KERNEL_PFKEY
+ SUBDIRS += plugins/kernel_pfkey
+ PLUGINS += kernel-pfkey
+endif
+
+if USE_KERNEL_KLIPS
+ SUBDIRS += plugins/kernel_klips
+ PLUGINS += kernel-klips
+endif
+
if USE_KERNEL_NETLINK
SUBDIRS += plugins/kernel_netlink
PLUGINS += kernel-netlink
@@ -164,6 +181,11 @@ if USE_SQL
PLUGINS += sql
endif
+if USE_UPDOWN
+ SUBDIRS += plugins/updown
+ PLUGINS += updown
+endif
+
if USE_EAP_IDENTITY
SUBDIRS += plugins/eap_identity
PLUGINS += eapidentity
diff --git a/src/charon/Makefile.in b/src/charon/Makefile.in
index 8d13f16e9..c8a817f45 100644
--- a/src/charon/Makefile.in
+++ b/src/charon/Makefile.in
@@ -50,36 +50,44 @@ ipsec_PROGRAMS = charon$(EXEEXT)
@USE_INTEGRITY_TEST_TRUE@am__append_4 = -DINTEGRITY_TEST
@USE_SELF_TEST_TRUE@am__append_5 = -DSELF_TEST
@USE_CAPABILITIES_TRUE@am__append_6 = -lcap
-@USE_KERNEL_NETLINK_TRUE@am__append_7 = plugins/kernel_netlink
-@USE_KERNEL_NETLINK_TRUE@am__append_8 = kernel-netlink
-@USE_STROKE_TRUE@am__append_9 = plugins/stroke
-@USE_STROKE_TRUE@am__append_10 = stroke
-@USE_SMP_TRUE@am__append_11 = plugins/smp
-@USE_SMP_TRUE@am__append_12 = smp
-@USE_SQL_TRUE@am__append_13 = plugins/sql
-@USE_SQL_TRUE@am__append_14 = sql
-@USE_EAP_IDENTITY_TRUE@am__append_15 = plugins/eap_identity
-@USE_EAP_IDENTITY_TRUE@am__append_16 = eapidentity
-@USE_EAP_SIM_TRUE@am__append_17 = plugins/eap_sim
-@USE_EAP_SIM_TRUE@am__append_18 = eapsim
-@USE_EAP_SIM_FILE_TRUE@am__append_19 = plugins/eap_sim_file
-@USE_EAP_SIM_FILE_TRUE@am__append_20 = eapsim-file
-@USE_EAP_MD5_TRUE@am__append_21 = plugins/eap_md5
-@USE_EAP_MD5_TRUE@am__append_22 = eapmd5
-@USE_EAP_GTC_TRUE@am__append_23 = plugins/eap_gtc
-@USE_EAP_GTC_TRUE@am__append_24 = eapgtc
-@USE_EAP_AKA_TRUE@am__append_25 = plugins/eap_aka
-@USE_EAP_AKA_TRUE@am__append_26 = eapaka
-@USE_MEDSRV_TRUE@am__append_27 = plugins/medsrv
-@USE_MEDSRV_TRUE@am__append_28 = medsrv
-@USE_MEDCLI_TRUE@am__append_29 = plugins/medcli
-@USE_MEDCLI_TRUE@am__append_30 = medcli
-@USE_NM_TRUE@am__append_31 = plugins/nm
-@USE_NM_TRUE@am__append_32 = nm
-@USE_UCI_TRUE@am__append_33 = plugins/uci
-@USE_UCI_TRUE@am__append_34 = uci
-@USE_UNIT_TESTS_TRUE@am__append_35 = plugins/unit_tester
-@USE_UNIT_TESTS_TRUE@am__append_36 = unit-tester
+@USE_LOAD_TESTS_TRUE@am__append_7 = plugins/load_tester
+@USE_LOAD_TESTS_TRUE@am__append_8 = load-tester
+@USE_KERNEL_PFKEY_TRUE@am__append_9 = plugins/kernel_pfkey
+@USE_KERNEL_PFKEY_TRUE@am__append_10 = kernel-pfkey
+@USE_KERNEL_KLIPS_TRUE@am__append_11 = plugins/kernel_klips
+@USE_KERNEL_KLIPS_TRUE@am__append_12 = kernel-klips
+@USE_KERNEL_NETLINK_TRUE@am__append_13 = plugins/kernel_netlink
+@USE_KERNEL_NETLINK_TRUE@am__append_14 = kernel-netlink
+@USE_STROKE_TRUE@am__append_15 = plugins/stroke
+@USE_STROKE_TRUE@am__append_16 = stroke
+@USE_SMP_TRUE@am__append_17 = plugins/smp
+@USE_SMP_TRUE@am__append_18 = smp
+@USE_SQL_TRUE@am__append_19 = plugins/sql
+@USE_SQL_TRUE@am__append_20 = sql
+@USE_UPDOWN_TRUE@am__append_21 = plugins/updown
+@USE_UPDOWN_TRUE@am__append_22 = updown
+@USE_EAP_IDENTITY_TRUE@am__append_23 = plugins/eap_identity
+@USE_EAP_IDENTITY_TRUE@am__append_24 = eapidentity
+@USE_EAP_SIM_TRUE@am__append_25 = plugins/eap_sim
+@USE_EAP_SIM_TRUE@am__append_26 = eapsim
+@USE_EAP_SIM_FILE_TRUE@am__append_27 = plugins/eap_sim_file
+@USE_EAP_SIM_FILE_TRUE@am__append_28 = eapsim-file
+@USE_EAP_MD5_TRUE@am__append_29 = plugins/eap_md5
+@USE_EAP_MD5_TRUE@am__append_30 = eapmd5
+@USE_EAP_GTC_TRUE@am__append_31 = plugins/eap_gtc
+@USE_EAP_GTC_TRUE@am__append_32 = eapgtc
+@USE_EAP_AKA_TRUE@am__append_33 = plugins/eap_aka
+@USE_EAP_AKA_TRUE@am__append_34 = eapaka
+@USE_MEDSRV_TRUE@am__append_35 = plugins/medsrv
+@USE_MEDSRV_TRUE@am__append_36 = medsrv
+@USE_MEDCLI_TRUE@am__append_37 = plugins/medcli
+@USE_MEDCLI_TRUE@am__append_38 = medcli
+@USE_NM_TRUE@am__append_39 = plugins/nm
+@USE_NM_TRUE@am__append_40 = nm
+@USE_UCI_TRUE@am__append_41 = plugins/uci
+@USE_UCI_TRUE@am__append_42 = uci
+@USE_UNIT_TESTS_TRUE@am__append_43 = plugins/unit_tester
+@USE_UNIT_TESTS_TRUE@am__append_44 = unit-tester
subdir = src/charon
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -154,6 +162,7 @@ am__charon_SOURCES_DIST = bus/bus.c bus/bus.h \
processing/jobs/delete_child_sa_job.h \
processing/jobs/delete_ike_sa_job.c \
processing/jobs/delete_ike_sa_job.h \
+ processing/jobs/migrate_job.c processing/jobs/migrate_job.h \
processing/jobs/process_message_job.c \
processing/jobs/process_message_job.h \
processing/jobs/rekey_child_sa_job.c \
@@ -185,10 +194,11 @@ am__charon_SOURCES_DIST = bus/bus.c bus/bus.h \
sa/authenticators/pubkey_authenticator.h sa/child_sa.c \
sa/child_sa.h sa/ike_sa.c sa/ike_sa.h sa/ike_sa_id.c \
sa/ike_sa_id.h sa/ike_sa_manager.c sa/ike_sa_manager.h \
- sa/task_manager.c sa/task_manager.h sa/tasks/child_create.c \
- sa/tasks/child_create.h sa/tasks/child_delete.c \
- sa/tasks/child_delete.h sa/tasks/child_rekey.c \
- sa/tasks/child_rekey.h sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
+ sa/task_manager.c sa/task_manager.h sa/keymat.c sa/keymat.h \
+ sa/tasks/child_create.c sa/tasks/child_create.h \
+ sa/tasks/child_delete.c sa/tasks/child_delete.h \
+ sa/tasks/child_rekey.c sa/tasks/child_rekey.h \
+ sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
sa/tasks/ike_cert_pre.c sa/tasks/ike_cert_pre.h \
sa/tasks/ike_cert_post.c sa/tasks/ike_cert_post.h \
sa/tasks/ike_config.c sa/tasks/ike_config.h \
@@ -242,17 +252,18 @@ am_charon_OBJECTS = bus.$(OBJEXT) file_logger.$(OBJEXT) \
kernel_ipsec.$(OBJEXT) packet.$(OBJEXT) receiver.$(OBJEXT) \
sender.$(OBJEXT) acquire_job.$(OBJEXT) callback_job.$(OBJEXT) \
delete_child_sa_job.$(OBJEXT) delete_ike_sa_job.$(OBJEXT) \
- process_message_job.$(OBJEXT) rekey_child_sa_job.$(OBJEXT) \
- rekey_ike_sa_job.$(OBJEXT) retransmit_job.$(OBJEXT) \
- send_dpd_job.$(OBJEXT) send_keepalive_job.$(OBJEXT) \
- roam_job.$(OBJEXT) update_sa_job.$(OBJEXT) scheduler.$(OBJEXT) \
+ migrate_job.$(OBJEXT) process_message_job.$(OBJEXT) \
+ rekey_child_sa_job.$(OBJEXT) rekey_ike_sa_job.$(OBJEXT) \
+ retransmit_job.$(OBJEXT) send_dpd_job.$(OBJEXT) \
+ send_keepalive_job.$(OBJEXT) roam_job.$(OBJEXT) \
+ update_sa_job.$(OBJEXT) scheduler.$(OBJEXT) \
processor.$(OBJEXT) authenticator.$(OBJEXT) \
eap_authenticator.$(OBJEXT) eap_method.$(OBJEXT) \
eap_manager.$(OBJEXT) sim_manager.$(OBJEXT) \
psk_authenticator.$(OBJEXT) pubkey_authenticator.$(OBJEXT) \
child_sa.$(OBJEXT) ike_sa.$(OBJEXT) ike_sa_id.$(OBJEXT) \
ike_sa_manager.$(OBJEXT) task_manager.$(OBJEXT) \
- child_create.$(OBJEXT) child_delete.$(OBJEXT) \
+ keymat.$(OBJEXT) child_create.$(OBJEXT) child_delete.$(OBJEXT) \
child_rekey.$(OBJEXT) ike_auth.$(OBJEXT) \
ike_cert_pre.$(OBJEXT) ike_cert_post.$(OBJEXT) \
ike_config.$(OBJEXT) ike_delete.$(OBJEXT) ike_dpd.$(OBJEXT) \
@@ -293,11 +304,12 @@ RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
ETAGS = etags
CTAGS = ctags
-DIST_SUBDIRS = . plugins/kernel_netlink plugins/stroke plugins/smp \
- plugins/sql plugins/eap_identity plugins/eap_sim \
- plugins/eap_sim_file plugins/eap_md5 plugins/eap_gtc \
- plugins/eap_aka plugins/medsrv plugins/medcli plugins/nm \
- plugins/uci plugins/unit_tester
+DIST_SUBDIRS = . plugins/load_tester plugins/kernel_pfkey \
+ plugins/kernel_klips plugins/kernel_netlink plugins/stroke \
+ plugins/smp plugins/sql plugins/updown plugins/eap_identity \
+ plugins/eap_sim plugins/eap_sim_file plugins/eap_md5 \
+ plugins/eap_gtc plugins/eap_aka plugins/medsrv plugins/medcli \
+ plugins/nm plugins/uci plugins/unit_tester
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
@@ -498,6 +510,7 @@ charon_SOURCES = bus/bus.c bus/bus.h bus/listeners/file_logger.c \
processing/jobs/delete_child_sa_job.h \
processing/jobs/delete_ike_sa_job.c \
processing/jobs/delete_ike_sa_job.h \
+ processing/jobs/migrate_job.c processing/jobs/migrate_job.h \
processing/jobs/process_message_job.c \
processing/jobs/process_message_job.h \
processing/jobs/rekey_child_sa_job.c \
@@ -529,10 +542,11 @@ charon_SOURCES = bus/bus.c bus/bus.h bus/listeners/file_logger.c \
sa/authenticators/pubkey_authenticator.h sa/child_sa.c \
sa/child_sa.h sa/ike_sa.c sa/ike_sa.h sa/ike_sa_id.c \
sa/ike_sa_id.h sa/ike_sa_manager.c sa/ike_sa_manager.h \
- sa/task_manager.c sa/task_manager.h sa/tasks/child_create.c \
- sa/tasks/child_create.h sa/tasks/child_delete.c \
- sa/tasks/child_delete.h sa/tasks/child_rekey.c \
- sa/tasks/child_rekey.h sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
+ sa/task_manager.c sa/task_manager.h sa/keymat.c sa/keymat.h \
+ sa/tasks/child_create.c sa/tasks/child_create.h \
+ sa/tasks/child_delete.c sa/tasks/child_delete.h \
+ sa/tasks/child_rekey.c sa/tasks/child_rekey.h \
+ sa/tasks/ike_auth.c sa/tasks/ike_auth.h \
sa/tasks/ike_cert_pre.c sa/tasks/ike_cert_pre.h \
sa/tasks/ike_cert_post.c sa/tasks/ike_cert_post.h \
sa/tasks/ike_config.c sa/tasks/ike_config.h \
@@ -568,13 +582,16 @@ SUBDIRS = . $(am__append_7) $(am__append_9) $(am__append_11) \
$(am__append_13) $(am__append_15) $(am__append_17) \
$(am__append_19) $(am__append_21) $(am__append_23) \
$(am__append_25) $(am__append_27) $(am__append_29) \
- $(am__append_31) $(am__append_33) $(am__append_35)
+ $(am__append_31) $(am__append_33) $(am__append_35) \
+ $(am__append_37) $(am__append_39) $(am__append_41) \
+ $(am__append_43)
PLUGINS = ${libstrongswan_plugins} $(am__append_8) $(am__append_10) \
$(am__append_12) $(am__append_14) $(am__append_16) \
$(am__append_18) $(am__append_20) $(am__append_22) \
$(am__append_24) $(am__append_26) $(am__append_28) \
$(am__append_30) $(am__append_32) $(am__append_34) \
- $(am__append_36)
+ $(am__append_36) $(am__append_38) $(am__append_40) \
+ $(am__append_42) $(am__append_44)
all: all-recursive
.SUFFIXES:
@@ -704,9 +721,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ke_payload.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_interface.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_ipsec.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keymat.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mediation_job.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mediation_manager.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/migrate_job.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nonce_payload.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notify_payload.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocsp_response_wrapper.Po@am__quote@
@@ -1410,6 +1429,20 @@ delete_ike_sa_job.obj: processing/jobs/delete_ike_sa_job.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o delete_ike_sa_job.obj `if test -f 'processing/jobs/delete_ike_sa_job.c'; then $(CYGPATH_W) 'processing/jobs/delete_ike_sa_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/delete_ike_sa_job.c'; fi`
+migrate_job.o: processing/jobs/migrate_job.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT migrate_job.o -MD -MP -MF $(DEPDIR)/migrate_job.Tpo -c -o migrate_job.o `test -f 'processing/jobs/migrate_job.c' || echo '$(srcdir)/'`processing/jobs/migrate_job.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/migrate_job.Tpo $(DEPDIR)/migrate_job.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/migrate_job.c' object='migrate_job.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o migrate_job.o `test -f 'processing/jobs/migrate_job.c' || echo '$(srcdir)/'`processing/jobs/migrate_job.c
+
+migrate_job.obj: processing/jobs/migrate_job.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT migrate_job.obj -MD -MP -MF $(DEPDIR)/migrate_job.Tpo -c -o migrate_job.obj `if test -f 'processing/jobs/migrate_job.c'; then $(CYGPATH_W) 'processing/jobs/migrate_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/migrate_job.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/migrate_job.Tpo $(DEPDIR)/migrate_job.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='processing/jobs/migrate_job.c' object='migrate_job.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o migrate_job.obj `if test -f 'processing/jobs/migrate_job.c'; then $(CYGPATH_W) 'processing/jobs/migrate_job.c'; else $(CYGPATH_W) '$(srcdir)/processing/jobs/migrate_job.c'; fi`
+
process_message_job.o: processing/jobs/process_message_job.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT process_message_job.o -MD -MP -MF $(DEPDIR)/process_message_job.Tpo -c -o process_message_job.o `test -f 'processing/jobs/process_message_job.c' || echo '$(srcdir)/'`processing/jobs/process_message_job.c
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/process_message_job.Tpo $(DEPDIR)/process_message_job.Po
@@ -1718,6 +1751,20 @@ task_manager.obj: sa/task_manager.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task_manager.obj `if test -f 'sa/task_manager.c'; then $(CYGPATH_W) 'sa/task_manager.c'; else $(CYGPATH_W) '$(srcdir)/sa/task_manager.c'; fi`
+keymat.o: sa/keymat.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT keymat.o -MD -MP -MF $(DEPDIR)/keymat.Tpo -c -o keymat.o `test -f 'sa/keymat.c' || echo '$(srcdir)/'`sa/keymat.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/keymat.Tpo $(DEPDIR)/keymat.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/keymat.c' object='keymat.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o keymat.o `test -f 'sa/keymat.c' || echo '$(srcdir)/'`sa/keymat.c
+
+keymat.obj: sa/keymat.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT keymat.obj -MD -MP -MF $(DEPDIR)/keymat.Tpo -c -o keymat.obj `if test -f 'sa/keymat.c'; then $(CYGPATH_W) 'sa/keymat.c'; else $(CYGPATH_W) '$(srcdir)/sa/keymat.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/keymat.Tpo $(DEPDIR)/keymat.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/keymat.c' object='keymat.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o keymat.obj `if test -f 'sa/keymat.c'; then $(CYGPATH_W) 'sa/keymat.c'; else $(CYGPATH_W) '$(srcdir)/sa/keymat.c'; fi`
+
child_create.o: sa/tasks/child_create.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT child_create.o -MD -MP -MF $(DEPDIR)/child_create.Tpo -c -o child_create.o `test -f 'sa/tasks/child_create.c' || echo '$(srcdir)/'`sa/tasks/child_create.c
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/child_create.Tpo $(DEPDIR)/child_create.Po
diff --git a/src/charon/bus/bus.c b/src/charon/bus/bus.c
index a102a3984..504947465 100644
--- a/src/charon/bus/bus.c
+++ b/src/charon/bus/bus.c
@@ -12,20 +12,18 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: bus.c 4198 2008-07-21 14:23:43Z martin $
+ * $Id: bus.c 4622 2008-11-11 10:52:37Z martin $
*/
#include "bus.h"
#include <pthread.h>
+#include <stdint.h>
#include <daemon.h>
#include <utils/mutex.h>
-ENUM(signal_names, SIG_ANY, SIG_MAX,
- /** should not get printed */
- "SIG_ANY",
- /** debugging message types */
+ENUM(debug_names, DBG_DMN, DBG_LIB,
"DMN",
"MGR",
"IKE",
@@ -36,19 +34,19 @@ ENUM(signal_names, SIG_ANY, SIG_MAX,
"NET",
"ENC",
"LIB",
- /** should not get printed */
- "SIG_DBG_MAX",
- /** all level0 signals are AUDIT signals */
- "AUD", "AUD", "AUD",
- "AUD", "AUD", "AUD",
- "AUD", "AUD", "AUD",
- "AUD", "AUD", "AUD",
- "AUD", "AUD", "AUD",
- "AUD", "AUD", "AUD",
- "AUD", "AUD", "AUD",
- "AUD", "AUD", "AUD",
- /** should not get printed */
- "SIG_MAX",
+);
+
+ENUM(debug_lower_names, DBG_DMN, DBG_LIB,
+ "dmn",
+ "mgr",
+ "ike",
+ "chd",
+ "job",
+ "cfg",
+ "knl",
+ "net",
+ "enc",
+ "lib",
);
typedef struct private_bus_t private_bus_t;
@@ -93,7 +91,7 @@ struct entry_t {
/**
* registered listener interface
*/
- bus_listener_t *listener;
+ listener_t *listener;
/**
* is this a active listen() call with a blocking thread
@@ -103,7 +101,7 @@ struct entry_t {
/**
* are we currently calling this listener
*/
- bool calling;
+ int calling;
/**
* condvar where active listeners wait
@@ -114,13 +112,13 @@ struct entry_t {
/**
* create a listener entry
*/
-static entry_t *entry_create(bus_listener_t *listener, bool blocker)
+static entry_t *entry_create(listener_t *listener, bool blocker)
{
entry_t *this = malloc_thing(entry_t);
this->listener = listener;
this->blocker = blocker;
- this->calling = FALSE;
+ this->calling = 0;
this->condvar = condvar_create(CONDVAR_DEFAULT);
return this;
@@ -140,12 +138,12 @@ static void entry_destroy(entry_t *entry)
* pthread_self returns large and ugly numbers, use this function
* for logging; these numbers are incremental starting at 1
*/
-static int get_thread_number(private_bus_t *this)
+static u_int get_thread_number(private_bus_t *this)
{
- static long current_num = 0;
- long stored_num;
+ static uintptr_t current_num = 0;
+ uintptr_t stored_num;
- stored_num = (long)pthread_getspecific(this->thread_id);
+ stored_num = (uintptr_t)pthread_getspecific(this->thread_id);
if (stored_num == 0)
{ /* first call of current thread */
pthread_setspecific(this->thread_id, (void*)++current_num);
@@ -160,7 +158,7 @@ static int get_thread_number(private_bus_t *this)
/**
* Implementation of bus_t.add_listener.
*/
-static void add_listener(private_bus_t *this, bus_listener_t *listener)
+static void add_listener(private_bus_t *this, listener_t *listener)
{
this->mutex->lock(this->mutex);
this->listeners->insert_last(this->listeners, entry_create(listener, FALSE));
@@ -170,23 +168,23 @@ static void add_listener(private_bus_t *this, bus_listener_t *listener)
/**
* Implementation of bus_t.remove_listener.
*/
-static void remove_listener(private_bus_t *this, bus_listener_t *listener)
+static void remove_listener(private_bus_t *this, listener_t *listener)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
entry_t *entry;
this->mutex->lock(this->mutex);
- iterator = this->listeners->create_iterator(this->listeners, TRUE);
- while (iterator->iterate(iterator, (void**)&entry))
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
{
if (entry->listener == listener)
{
- iterator->remove(iterator);
+ this->listeners->remove_at(this->listeners, enumerator);
entry_destroy(entry);
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
}
@@ -207,26 +205,14 @@ struct cleanup_data_t {
*/
static void listener_cleanup(cleanup_data_t *data)
{
- iterator_t *iterator;
- entry_t *entry;
-
- iterator = data->this->listeners->create_iterator(data->this->listeners, TRUE);
- while (iterator->iterate(iterator, (void**)&entry))
- {
- if (entry == data->entry)
- {
- iterator->remove(iterator);
- entry_destroy(entry);
- break;
- }
- }
- iterator->destroy(iterator);
+ data->this->listeners->remove(data->this->listeners, data->entry, NULL);
+ entry_destroy(data->entry);
}
/**
* Implementation of bus_t.listen.
*/
-static void listen_(private_bus_t *this, bus_listener_t *listener, job_t *job)
+static void listen_(private_bus_t *this, listener_t *listener, job_t *job)
{
int old;
cleanup_data_t data;
@@ -267,33 +253,31 @@ typedef struct {
ike_sa_t *ike_sa;
/** invoking thread */
long thread;
- /** signal type */
- signal_t signal;
- /** signal level */
+ /** debug group */
+ debug_t group;
+ /** debug level */
level_t level;
- /** signal specific user data */
- void *user;
/** format string */
char *format;
/** argument list */
va_list args;
-} signal_data_t;
+} log_data_t;
/**
- * listener invocation as a list remove callback
+ * listener->log() invocation as a list remove callback
*/
-static bool signal_cb(entry_t *entry, signal_data_t *data)
+static bool log_cb(entry_t *entry, log_data_t *data)
{
va_list args;
- if (entry->calling)
+ if (entry->calling || !entry->listener->log)
{ /* avoid recursive calls */
return FALSE;
}
- entry->calling = TRUE;
+ entry->calling++;
va_copy(args, data->args);
- if (!entry->listener->signal(entry->listener, data->signal, data->level,
- data->thread, data->ike_sa, data->user, data->format, args))
+ if (!entry->listener->log(entry->listener, data->group, data->level,
+ data->thread, data->ike_sa, data->format, args))
{
if (entry->blocker)
{
@@ -305,52 +289,238 @@ static bool signal_cb(entry_t *entry, signal_data_t *data)
entry_destroy(entry);
}
va_end(args);
- entry->calling = FALSE;
+ entry->calling--;
return TRUE;
}
va_end(args);
- entry->calling = FALSE;
+ entry->calling--;
return FALSE;
}
/**
- * Implementation of bus_t.vsignal.
+ * Implementation of bus_t.vlog.
*/
-static void vsignal(private_bus_t *this, signal_t signal, level_t level,
- void *user, char* format, va_list args)
+static void vlog(private_bus_t *this, debug_t group, level_t level,
+ char* format, va_list args)
{
- signal_data_t data;
+ log_data_t data;
data.ike_sa = pthread_getspecific(this->thread_sa);
data.thread = get_thread_number(this);
- data.signal = signal;
+ data.group = group;
data.level = level;
- data.user = user;
data.format = format;
va_copy(data.args, args);
this->mutex->lock(this->mutex);
- /* we use the remove() method to invoke all listeners with small overhead */
- this->listeners->remove(this->listeners, &data, (void*)signal_cb);
+ /* We use the remove() method to invoke all listeners. This is cheap and
+ * does not require an allocation for this performance critical function. */
+ this->listeners->remove(this->listeners, &data, (void*)log_cb);
this->mutex->unlock(this->mutex);
va_end(data.args);
}
/**
- * Implementation of bus_t.signal.
+ * Implementation of bus_t.log.
*/
-static void signal_(private_bus_t *this, signal_t signal, level_t level,
- void* data, char* format, ...)
+static void log_(private_bus_t *this, debug_t group, level_t level,
+ char* format, ...)
{
va_list args;
va_start(args, format);
- vsignal(this, signal, level, data, format, args);
+ vlog(this, group, level, format, args);
va_end(args);
}
/**
+ * unregister a listener
+ */
+static void unregister_listener(private_bus_t *this, entry_t *entry,
+ enumerator_t *enumerator)
+{
+ if (entry->blocker)
+ {
+ entry->blocker = FALSE;
+ entry->condvar->signal(entry->condvar);
+ }
+ else
+ {
+ entry_destroy(entry);
+ }
+ this->listeners->remove_at(this->listeners, enumerator);
+}
+
+/**
+ * Implementation of bus_t.ike_state_change
+ */
+static void ike_state_change(private_bus_t *this, ike_sa_t *ike_sa,
+ ike_sa_state_t state)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ bool keep;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->ike_state_change)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->ike_state_change(entry->listener, ike_sa, state);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of bus_t.child_state_change
+ */
+static void child_state_change(private_bus_t *this, child_sa_t *child_sa,
+ child_sa_state_t state)
+{
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ entry_t *entry;
+ bool keep;
+
+ ike_sa = pthread_getspecific(this->thread_sa);
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->child_state_change)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->child_state_change(entry->listener, ike_sa,
+ child_sa, state);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of bus_t.message
+ */
+static void message(private_bus_t *this, message_t *message, bool incoming)
+{
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ entry_t *entry;
+ bool keep;
+
+ ike_sa = pthread_getspecific(this->thread_sa);
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->message)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->message(entry->listener, ike_sa,
+ message, incoming);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of bus_t.ike_keys
+ */
+static void ike_keys(private_bus_t *this, ike_sa_t *ike_sa,
+ diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r,
+ ike_sa_t *rekey)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ bool keep;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->ike_keys)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->ike_keys(entry->listener, ike_sa, dh,
+ nonce_i, nonce_r, rekey);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Implementation of bus_t.child_keys
+ */
+static void child_keys(private_bus_t *this, child_sa_t *child_sa,
+ diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r)
+{
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ entry_t *entry;
+ bool keep;
+
+ ike_sa = pthread_getspecific(this->thread_sa);
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->child_keys)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->child_keys(entry->listener, ike_sa, child_sa,
+ dh, nonce_i, nonce_r);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
* Implementation of bus_t.destroy.
*/
static void destroy(private_bus_t *this)
@@ -367,16 +537,21 @@ bus_t *bus_create()
{
private_bus_t *this = malloc_thing(private_bus_t);
- this->public.add_listener = (void(*)(bus_t*,bus_listener_t*))add_listener;
- this->public.remove_listener = (void(*)(bus_t*,bus_listener_t*))remove_listener;
- this->public.listen = (void(*)(bus_t*, bus_listener_t *listener, job_t *job))listen_;
+ this->public.add_listener = (void(*)(bus_t*,listener_t*))add_listener;
+ this->public.remove_listener = (void(*)(bus_t*,listener_t*))remove_listener;
+ this->public.listen = (void(*)(bus_t*, listener_t *listener, job_t *job))listen_;
this->public.set_sa = (void(*)(bus_t*,ike_sa_t*))set_sa;
- this->public.signal = (void(*)(bus_t*,signal_t,level_t,void*,char*,...))signal_;
- this->public.vsignal = (void(*)(bus_t*,signal_t,level_t,void*,char*,va_list))vsignal;
+ this->public.log = (void(*)(bus_t*,debug_t,level_t,char*,...))log_;
+ this->public.vlog = (void(*)(bus_t*,debug_t,level_t,char*,va_list))vlog;
+ this->public.ike_state_change = (void(*)(bus_t*,ike_sa_t*,ike_sa_state_t))ike_state_change;
+ this->public.child_state_change = (void(*)(bus_t*,child_sa_t*,child_sa_state_t))child_state_change;
+ this->public.message = (void(*)(bus_t*, message_t *message, bool incoming))message;
+ this->public.ike_keys = (void(*)(bus_t*, ike_sa_t *ike_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey))ike_keys;
+ this->public.child_keys = (void(*)(bus_t*, child_sa_t *child_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r))child_keys;
this->public.destroy = (void(*)(bus_t*)) destroy;
this->listeners = linked_list_create();
- this->mutex = mutex_create(MUTEX_DEFAULT);
+ this->mutex = mutex_create(MUTEX_RECURSIVE);
pthread_key_create(&this->thread_id, NULL);
pthread_key_create(&this->thread_sa, NULL);
diff --git a/src/charon/bus/bus.h b/src/charon/bus/bus.h
index db417064f..383678488 100644
--- a/src/charon/bus/bus.h
+++ b/src/charon/bus/bus.h
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: bus.h 4192 2008-07-18 15:51:40Z martin $
+ * $Id: bus.h 4622 2008-11-11 10:52:37Z martin $
*/
/**
@@ -23,9 +23,9 @@
#ifndef BUS_H_
#define BUS_H_
-typedef enum signal_t signal_t;
+typedef enum debug_t debug_t;
typedef enum level_t level_t;
-typedef struct bus_listener_t bus_listener_t;
+typedef struct listener_t listener_t;
typedef struct bus_t bus_t;
#include <stdarg.h>
@@ -34,145 +34,87 @@ typedef struct bus_t bus_t;
#include <sa/child_sa.h>
#include <processing/jobs/job.h>
-
/**
- * signals emitted by the daemon.
- *
- * Signaling is for different purporses. First, it allows debugging via
- * "debugging signal messages", sencondly, it allows to follow certain
- * mechanisms currently going on in the daemon. As we are multithreaded,
- * and multiple transactions are involved, it's not possible to follow
- * one connection setup without further infrastructure. These infrastructure
- * is provided by the bus and the signals the daemon emits to the bus.
- *
- * There are different scenarios to follow these signals, but all have
- * the same scheme. First, a START signal is emitted to indicate the daemon
- * has started to do something. After a start signal, a SUCCESS or a FAILED
- * signal of the same type follows. This allows to track the operation. Any
- * Debug signal betwee a START and a SUCCESS/FAILED belongs to that operation
- * if the IKE_SA is the same. The thread may change, as multiple threads
- * may be involved in a complex scenario.
+ * Debug message group.
*/
-enum signal_t {
- /** pseudo signal, representing any other signal */
- SIG_ANY,
-
- /** debugging message from daemon main loop */
+enum debug_t {
+ /** daemon main loop */
DBG_DMN,
- /** debugging message from IKE_SA_MANAGER */
+ /** IKE_SA_MANAGER */
DBG_MGR,
- /** debugging message from an IKE_SA */
+ /** IKE_SA */
DBG_IKE,
- /** debugging message from a CHILD_SA */
+ /** CHILD_SA */
DBG_CHD,
- /** debugging message from job processing */
+ /** job processing */
DBG_JOB,
- /** debugging message from configuration backends */
+ /** configuration backends */
DBG_CFG,
- /** debugging message from kernel interface */
+ /** kernel interface */
DBG_KNL,
- /** debugging message from networking */
+ /** networking/sockets */
DBG_NET,
- /** debugging message from message encoding/decoding */
+ /** message encoding/decoding */
DBG_ENC,
- /** debugging message from libstrongswan via logging hook */
+ /** libstrongswan via logging hook */
DBG_LIB,
-
- /** number of debug signals */
+ /** number of groups */
DBG_MAX,
-
- /** signals for IKE_SA establishment */
- IKE_UP_START,
- IKE_UP_SUCCESS,
- IKE_UP_FAILED,
-
- /** signals for IKE_SA delete */
- IKE_DOWN_START,
- IKE_DOWN_SUCCESS,
- IKE_DOWN_FAILED,
-
- /** signals for IKE_SA rekeying */
- IKE_REKEY_START,
- IKE_REKEY_SUCCESS,
- IKE_REKEY_FAILED,
-
- /** signals for CHILD_SA establishment */
- CHD_UP_START,
- CHD_UP_SUCCESS,
- CHD_UP_FAILED,
-
- /** signals for CHILD_SA delete */
- CHD_DOWN_START,
- CHD_DOWN_SUCCESS,
- CHD_DOWN_FAILED,
-
- /** signals for CHILD_SA rekeying */
- CHD_REKEY_START,
- CHD_REKEY_SUCCESS,
- CHD_REKEY_FAILED,
-
- /** signals for CHILD_SA routing */
- CHD_ROUTE_START,
- CHD_ROUTE_SUCCESS,
- CHD_ROUTE_FAILED,
-
- /** signals for CHILD_SA routing */
- CHD_UNROUTE_START,
- CHD_UNROUTE_SUCCESS,
- CHD_UNROUTE_FAILED,
-
- SIG_MAX
+ /** pseudo group with all groups */
+ DBG_ANY = DBG_MAX,
};
/**
- * short names of signals using 3 chars
+ * short names of debug message group.
*/
-extern enum_name_t *signal_names;
+extern enum_name_t *debug_names;
/**
- * Signal levels used to control output verbosity.
+ * short names of debug message group, lower case.
+ */
+extern enum_name_t *debug_lower_names;
+
+/**
+ * Debug levels used to control output verbosity.
*/
enum level_t {
- /** numerical levels from 0 to 4 */
- LEVEL_0 = 0,
- LEVEL_1 = 1,
- LEVEL_2 = 2,
- LEVEL_3 = 3,
- LEVEL_4 = 4,
- /** absolutely silent, no signal is emitted with this level */
- LEVEL_SILENT = -1,
- /** alias for numberical levels */
- LEVEL_AUDIT = LEVEL_0,
- LEVEL_CTRL = LEVEL_1,
- LEVEL_CTRLMORE = LEVEL_2,
- LEVEL_RAW = LEVEL_3,
- LEVEL_PRIVATE = LEVEL_4,
+ /** absolutely silent */
+ LEVEL_SILENT = -1,
+ /** most important auditing logs */
+ LEVEL_AUDIT = 0,
+ /** control flow */
+ LEVEL_CTRL = 1,
+ /** diagnose problems */
+ LEVEL_DIAG = 2,
+ /** raw binary blobs */
+ LEVEL_RAW = 3,
+ /** including sensitive data (private keys) */
+ LEVEL_PRIVATE = 4,
};
#ifndef DEBUG_LEVEL
# define DEBUG_LEVEL 4
#endif /* DEBUG_LEVEL */
+#if DEBUG_LEVEL >= 0
+#define DBG0(group, format, ...) charon->bus->log(charon->bus, group, 0, format, ##__VA_ARGS__)
+#endif /* DEBUG_LEVEL >= 0 */
#if DEBUG_LEVEL >= 1
-/**
- * Log a debug message via the signal bus.
- *
- * @param signal signal_t signal description
- * @param format printf() style format string
- * @param ... printf() style agument list
- */
-# define DBG1(sig, format, ...) charon->bus->signal(charon->bus, sig, LEVEL_1, NULL, format, ##__VA_ARGS__)
-#endif /* DEBUG_LEVEL */
+#define DBG1(group, format, ...) charon->bus->log(charon->bus, group, 1, format, ##__VA_ARGS__)
+#endif /* DEBUG_LEVEL >= 1 */
#if DEBUG_LEVEL >= 2
-#define DBG2(sig, format, ...) charon->bus->signal(charon->bus, sig, LEVEL_2, NULL, format, ##__VA_ARGS__)
-#endif /* DEBUG_LEVEL */
+#define DBG2(group, format, ...) charon->bus->log(charon->bus, group, 2, format, ##__VA_ARGS__)
+#endif /* DEBUG_LEVEL >= 2 */
#if DEBUG_LEVEL >= 3
-#define DBG3(sig, format, ...) charon->bus->signal(charon->bus, sig, LEVEL_3, NULL, format, ##__VA_ARGS__)
-#endif /* DEBUG_LEVEL */
+#define DBG3(group, format, ...) charon->bus->log(charon->bus, group, 3, format, ##__VA_ARGS__)
+#endif /* DEBUG_LEVEL >= 3 */
#if DEBUG_LEVEL >= 4
-#define DBG4(sig, format, ...) charon->bus->signal(charon->bus, sig, LEVEL_4, NULL, format, ##__VA_ARGS__)
-#endif /* DEBUG_LEVEL */
+#define DBG4(group, format, ...) charon->bus->log(charon->bus, group, 4, format, ##__VA_ARGS__)
+#endif /* DEBUG_LEVEL >= 4 */
+#ifndef DBG0
+# define DBG0(...) {}
+#endif /* DBG0 */
#ifndef DBG1
# define DBG1(...) {}
#endif /* DBG1 */
@@ -186,101 +128,115 @@ enum level_t {
# define DBG4(...) {}
#endif /* DBG4 */
-/**
- * Raise a signal for an IKE_SA event.
- *
- * @param sig signal_t signal description
- * @param format printf() style format string
- * @param ... printf() style agument list
- */
-#define SIG_IKE(sig, format, ...) charon->bus->signal(charon->bus, IKE_##sig, LEVEL_0, NULL, format, ##__VA_ARGS__)
/**
- * Raise a signal for an IKE event.
- *
- * @param sig signal_t signal description
- * @param format printf() style format string
- * @param ... printf() style agument list
- */
-#define SIG_CHD(sig, chd, format, ...) charon->bus->signal(charon->bus, CHD_##sig, LEVEL_0, chd, format, ##__VA_ARGS__)
-
-/**
- * Get the type of a signal.
- *
- * A signal may be a debugging signal with a specific context. They have
- * a level specific for their context > 0. All audit signals use the
- * type 0. This allows filtering of singals by their type.
- *
- * @param signal signal to get the type from
- * @return type of the signal, between 0..(DBG_MAX-1)
- */
-#define SIG_TYPE(sig) (sig > DBG_MAX ? SIG_ANY : sig)
-
-
-/**
- * Interface for registering at the signal bus.
- *
- * To receive signals from the bus, the client implementing the
- * bus_listener_t interface registers itself at the signal bus.
+ * Listener interface, listens to events if registered to the bus.
*/
-struct bus_listener_t {
+struct listener_t {
/**
- * Send a signal to a bus listener.
+ * Log a debugging message.
*
- * A numerical identification for the thread is included, as the
- * associated IKE_SA, if any. Signal specifies the type of
- * the event occured. The format string specifies
- * an additional informational or error message with a printf() like
- * variable argument list. This is in the va_list form, as forwarding
- * a "..." parameters to functions is not (cleanly) possible.
* The implementing signal function returns TRUE to stay registered
* to the bus, or FALSE to unregister itself.
- * Calling bus_t.signal() inside of a registered listener is possible,
+ * Calling bus_t.log() inside of a registered listener is possible,
* but the bus does not invoke listeners recursively.
*
* @param singal kind of the signal (up, down, rekeyed, ...)
* @param level verbosity level of the signal
* @param thread ID of the thread raised this signal
* @param ike_sa IKE_SA associated to the event
- * @param data additional signal specific user data
* @param format printf() style format string
* @param args vprintf() style va_list argument list
" @return TRUE to stay registered, FALSE to unregister
*/
- bool (*signal) (bus_listener_t *this, signal_t signal, level_t level,
- int thread, ike_sa_t *ike_sa, void *data,
- char* format, va_list args);
+ bool (*log) (listener_t *this, debug_t group, level_t level, int thread,
+ ike_sa_t *ike_sa, char* format, va_list args);
+
+ /**
+ * Handle state changes in an IKE_SA.
+ *
+ * @param ike_sa IKE_SA which changes its state
+ * @param state new IKE_SA state this IKE_SA changes to
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*ike_state_change)(listener_t *this, ike_sa_t *ike_sa,
+ ike_sa_state_t state);
+
+ /**
+ * Handle state changes in a CHILD_SA.
+ *
+ * @param ike_sa IKE_SA containing the affected CHILD_SA
+ * @param child_sa CHILD_SA which changes its state
+ * @param state new CHILD_SA state this CHILD_SA changes to
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*child_state_change)(listener_t *this, ike_sa_t *ike_sa,
+ child_sa_t *child_sa, child_sa_state_t state);
+
+ /**
+ * Hook called for received/sent messages of an IKE_SA.
+ *
+ * @param ike_sa IKE_SA sending/receving a message
+ * @param message message object
+ * @param incoming TRUE for incoming messages, FALSE for outgoing
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*message)(listener_t *this, ike_sa_t *ike_sa, message_t *message,
+ bool incoming);
+
+ /**
+ * Hook called with IKE_SA key material.
+ *
+ * @param ike_sa IKE_SA this keymat belongs to
+ * @param dh diffie hellman shared secret
+ * @param nonce_i initiators nonce
+ * @param nonce_r responders nonce
+ * @param rekey IKE_SA we are rekeying, if any
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*ike_keys)(listener_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey);
+
+ /**
+ * Hook called with CHILD_SA key material.
+ *
+ * @param ike_sa IKE_SA the child sa belongs to
+ * @param child_sa CHILD_SA this keymat is used for
+ * @param dh diffie hellman shared secret
+ * @param nonce_i initiators nonce
+ * @param nonce_r responders nonce
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*child_keys)(listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
+ diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r);
};
/**
- * Signal bus which sends signals to registered listeners.
+ * The bus receives events and sends them to all registered listeners.
*
- * The signal bus is not much more than a multiplexer. A listener interested
- * in receiving event signals registers at the bus. Any signals sent to
- * are delivered to all registered listeners.
- * To deliver signals to threads, the blocking listen() call may be used
- * to wait for a signal.
+ * Any events sent to are delivered to all registered listeners. Threads
+ * may wait actively to events using the blocking listen() call.
*/
struct bus_t {
/**
* Register a listener to the bus.
*
- * A registered listener receives all signals which are sent to the bus.
- * The listener is passive; the thread which emitted the signal
+ * A registered listener receives all events which are sent to the bus.
+ * The listener is passive; the thread which emitted the event
* processes the listener routine.
*
* @param listener listener to register.
*/
- void (*add_listener) (bus_t *this, bus_listener_t *listener);
+ void (*add_listener) (bus_t *this, listener_t *listener);
/**
* Unregister a listener from the bus.
*
* @param listener listener to unregister.
*/
- void (*remove_listener) (bus_t *this, bus_listener_t *listener);
+ void (*remove_listener) (bus_t *this, listener_t *listener);
/**
* Register a listener and block the calling thread.
@@ -288,69 +244,109 @@ struct bus_t {
* This call registers a listener and blocks the calling thread until
* its listeners function returns FALSE. This allows to wait for certain
* events. The associated job is executed after the listener has been
- * registered, this allows to listen on events we initiate with the job
- * without missing any signals.
+ * registered: This allows to listen on events we initiate with the job,
+ * without missing any events to job may fire.
*
* @param listener listener to register
* @param job job to execute asynchronously when registered, or NULL
*/
- void (*listen)(bus_t *this, bus_listener_t *listener, job_t *job);
+ void (*listen)(bus_t *this, listener_t *listener, job_t *job);
/**
* Set the IKE_SA the calling thread is using.
*
- * To associate an received signal to an IKE_SA without passing it as
- * parameter each time, the thread registers it's used IKE_SA each
- * time it checked it out. Before checking it in, the thread unregisters
- * the IKE_SA (by passing NULL). This IKE_SA is stored per-thread, so each
- * thread has one IKE_SA registered (or not).
+ * To associate an received log message to an IKE_SA without passing it as
+ * parameter each time, the thread registers the currenlty used IKE_SA
+ * during check-out. Before check-in, the thread unregisters the IKE_SA.
+ * This IKE_SA is stored per-thread, so each thread has its own IKE_SA
+ * registered.
*
* @param ike_sa ike_sa to register, or NULL to unregister
*/
void (*set_sa) (bus_t *this, ike_sa_t *ike_sa);
/**
- * Send a signal to the bus.
+ * Send a log message to the bus.
*
* The signal specifies the type of the event occured. The format string
* specifies an additional informational or error message with a
* printf() like variable argument list.
- * Some useful macros are available to shorten this call.
- * @see SIG(), DBG1()
+ * Use the DBG() macros.
*
- * @param singal kind of the signal (up, down, rekeyed, ...)
+ * @param group debugging group
* @param level verbosity level of the signal
- * @param data additional signal specific user data
* @param format printf() style format string
* @param ... printf() style argument list
*/
- void (*signal) (bus_t *this, signal_t signal, level_t level,
- void *data, char* format, ...);
+ void (*log)(bus_t *this, debug_t group, level_t level, char* format, ...);
/**
- * Send a signal to the bus using va_list arguments.
+ * Send a log message to the bus using va_list arguments.
*
* Same as bus_t.signal(), but uses va_list argument list.
*
- * @param singal kind of the signal (up, down, rekeyed, ...)
+ * @param group kind of the signal (up, down, rekeyed, ...)
* @param level verbosity level of the signal
- * @param data additional signal specific user data
* @param format printf() style format string
* @param args va_list arguments
*/
- void (*vsignal) (bus_t *this, signal_t signal, level_t level,
- void *data, char* format, va_list args);
+ void (*vlog)(bus_t *this, debug_t group, level_t level,
+ char* format, va_list args);
+ /**
+ * Send a IKE_SA state change event to the bus.
+ *
+ * @param ike_sa IKE_SA which changes its state
+ * @param state new state IKE_SA changes to
+ */
+ void (*ike_state_change)(bus_t *this, ike_sa_t *ike_sa,
+ ike_sa_state_t state);
+ /**
+ * Send a CHILD_SA state change event to the bus.
+ *
+ * @param child_sa CHILD_SA which changes its state
+ * @param state new state CHILD_SA changes to
+ */
+ void (*child_state_change)(bus_t *this, child_sa_t *child_sa,
+ child_sa_state_t state);
+ /**
+ * Message send/receive hook.
+ *
+ * @param message message to send/receive
+ * @param incoming TRUE for incoming messages, FALSE for outgoing
+ */
+ void (*message)(bus_t *this, message_t *message, bool incoming);
/**
- * Destroy the signal bus.
+ * IKE_SA keymat hook.
+ *
+ * @param ike_sa IKE_SA this keymat belongs to
+ * @param dh diffie hellman shared secret
+ * @param nonce_i initiators nonce
+ * @param nonce_r responders nonce
+ * @param rekey IKE_SA we are rekeying, if any
+ */
+ void (*ike_keys)(bus_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey);
+ /**
+ * CHILD_SA keymat hook.
+ *
+ * @param child_sa CHILD_SA this keymat is used for
+ * @param dh diffie hellman shared secret
+ * @param nonce_i initiators nonce
+ * @param nonce_r responders nonce
+ */
+ void (*child_keys)(bus_t *this, child_sa_t *child_sa, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r);
+ /**
+ * Destroy the event bus.
*/
void (*destroy) (bus_t *this);
};
/**
- * Create the signal bus which multiplexes signals to its listeners.
+ * Create the event bus which forwards events to its listeners.
*
- * @return signal bus instance
+ * @return event bus instance
*/
bus_t *bus_create();
diff --git a/src/charon/bus/listeners/file_logger.c b/src/charon/bus/listeners/file_logger.c
index 8a7f66360..4259630ec 100644
--- a/src/charon/bus/listeners/file_logger.c
+++ b/src/charon/bus/listeners/file_logger.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: file_logger.c 4192 2008-07-18 15:51:40Z martin $
+ * $Id: file_logger.c 4622 2008-11-11 10:52:37Z martin $
*/
#include <stdio.h>
@@ -39,20 +39,18 @@ struct private_file_logger_t {
FILE *out;
/**
- * Maximum level to log
+ * Maximum level to log, for each group
*/
level_t levels[DBG_MAX];
};
-
/**
- * Implementation of bus_listener_t.signal.
+ * Implementation of bus_listener_t.log.
*/
-static bool signal_(private_file_logger_t *this, signal_t signal, level_t level,
- int thread, ike_sa_t* ike_sa, void *data,
- char *format, va_list args)
+static bool log_(private_file_logger_t *this, debug_t group, level_t level,
+ int thread, ike_sa_t* ike_sa, char *format, va_list args)
{
- if (level <= this->levels[SIG_TYPE(signal)])
+ if (level <= this->levels[group])
{
char buffer[8192];
char *current = buffer, *next;
@@ -68,7 +66,8 @@ static bool signal_(private_file_logger_t *this, signal_t signal, level_t level,
{
*(next++) = '\0';
}
- fprintf(this->out, "%.2d[%N] %s\n", thread, signal_names, signal, current);
+ fprintf(this->out, "%.2d[%N] %s\n",
+ thread, debug_names, group, current);
current = next;
}
}
@@ -79,20 +78,18 @@ static bool signal_(private_file_logger_t *this, signal_t signal, level_t level,
/**
* Implementation of file_logger_t.set_level.
*/
-static void set_level(private_file_logger_t *this, signal_t signal, level_t level)
+static void set_level(private_file_logger_t *this, debug_t group, level_t level)
{
- if (signal == SIG_ANY)
+ if (group < DBG_ANY)
{
- int i;
- for (i = 0; i < DBG_MAX; i++)
- {
- this->levels[i] = level;
- }
+ this->levels[group] = level;
}
else
{
-
- this->levels[SIG_TYPE(signal)] = level;
+ for (group = 0; group < DBG_MAX; group++)
+ {
+ this->levels[group] = level;
+ }
}
}
@@ -101,6 +98,10 @@ static void set_level(private_file_logger_t *this, signal_t signal, level_t leve
*/
static void destroy(private_file_logger_t *this)
{
+ if (this->out != stdout && this->out != stderr)
+ {
+ fclose(this->out);
+ }
free(this);
}
@@ -112,13 +113,15 @@ file_logger_t *file_logger_create(FILE *out)
private_file_logger_t *this = malloc_thing(private_file_logger_t);
/* public functions */
- this->public.listener.signal = (bool(*)(bus_listener_t*,signal_t,level_t,int,ike_sa_t*,void*,char*,va_list))signal_;
- this->public.set_level = (void(*)(file_logger_t*,signal_t,level_t))set_level;
+ memset(&this->public.listener, 0, sizeof(listener_t));
+ this->public.listener.log = (bool(*)(listener_t*,debug_t,level_t,int,ike_sa_t*,char*,va_list))log_;
+ this->public.set_level = (void(*)(file_logger_t*,debug_t,level_t))set_level;
this->public.destroy = (void(*)(file_logger_t*))destroy;
/* private variables */
this->out = out;
- set_level(this, SIG_ANY, LEVEL_SILENT);
+ set_level(this, DBG_ANY, LEVEL_SILENT);
return &this->public;
}
+
diff --git a/src/charon/bus/listeners/file_logger.h b/src/charon/bus/listeners/file_logger.h
index 86b79c002..18a7c9765 100644
--- a/src/charon/bus/listeners/file_logger.h
+++ b/src/charon/bus/listeners/file_logger.h
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: file_logger.h 3589 2008-03-13 14:14:44Z martin $
+ * $Id: file_logger.h 4434 2008-10-14 08:52:13Z martin $
*/
/**
@@ -28,22 +28,22 @@ typedef struct file_logger_t file_logger_t;
#include <bus/bus.h>
/**
- * Logger to files which implements bus_listener_t.
+ * Logger to files which implements listener_t.
*/
struct file_logger_t {
/**
- * Implements the bus_listener_t interface.
+ * Implements the listener_t interface.
*/
- bus_listener_t listener;
+ listener_t listener;
/**
- * Set the loglevel for a signal type.
+ * Set the loglevel for a debug group.
*
- * @param singal type of signal
+ * @param group debug group to set
* @param level max level to log (0..4)
*/
- void (*set_level) (file_logger_t *this, signal_t signal, level_t level);
+ void (*set_level) (file_logger_t *this, debug_t group, level_t level);
/**
* Destroys a file_logger_t object.
diff --git a/src/charon/bus/listeners/sys_logger.c b/src/charon/bus/listeners/sys_logger.c
index 4f5b6fc3b..37dbce926 100644
--- a/src/charon/bus/listeners/sys_logger.c
+++ b/src/charon/bus/listeners/sys_logger.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: sys_logger.c 4192 2008-07-18 15:51:40Z martin $
+ * $Id: sys_logger.c 4434 2008-10-14 08:52:13Z martin $
*/
#include <stdio.h>
@@ -40,20 +40,18 @@ struct private_sys_logger_t {
int facility;
/**
- * Maximum level to log
+ * Maximum level to log, for each group
*/
level_t levels[DBG_MAX];
};
-
/**
- * Implementation of bus_listener_t.signal.
+ * Implementation of listener_t.log.
*/
-static bool signal_(private_sys_logger_t *this, signal_t signal, level_t level,
- int thread, ike_sa_t* ike_sa, void *data,
- char *format, va_list args)
+static bool log_(private_sys_logger_t *this, debug_t group, level_t level,
+ int thread, ike_sa_t* ike_sa, char *format, va_list args)
{
- if (level <= this->levels[SIG_TYPE(signal)])
+ if (level <= this->levels[group])
{
char buffer[8192];
char *current = buffer, *next;
@@ -70,7 +68,7 @@ static bool signal_(private_sys_logger_t *this, signal_t signal, level_t level,
*(next++) = '\0';
}
syslog(this->facility|LOG_INFO, "%.2d[%N] %s\n",
- thread, signal_names, signal, current);
+ thread, debug_names, group, current);
current = next;
}
}
@@ -81,20 +79,18 @@ static bool signal_(private_sys_logger_t *this, signal_t signal, level_t level,
/**
* Implementation of sys_logger_t.set_level.
*/
-static void set_level(private_sys_logger_t *this, signal_t signal, level_t level)
+static void set_level(private_sys_logger_t *this, debug_t group, level_t level)
{
- if (signal == SIG_ANY)
+ if (group < DBG_ANY)
{
- int i;
- for (i = 0; i < DBG_MAX; i++)
- {
- this->levels[i] = level;
- }
+ this->levels[group] = level;
}
else
{
-
- this->levels[SIG_TYPE(signal)] = level;
+ for (group = 0; group < DBG_MAX; group++)
+ {
+ this->levels[group] = level;
+ }
}
}
@@ -115,13 +111,14 @@ sys_logger_t *sys_logger_create(int facility)
private_sys_logger_t *this = malloc_thing(private_sys_logger_t);
/* public functions */
- this->public.listener.signal = (bool(*)(bus_listener_t*,signal_t,level_t,int,ike_sa_t*,void*,char*,va_list))signal_;
- this->public.set_level = (void(*)(sys_logger_t*,signal_t,level_t))set_level;
+ memset(&this->public.listener, 0, sizeof(listener_t));
+ this->public.listener.log = (bool(*)(listener_t*,debug_t,level_t,int,ike_sa_t*,char*,va_list))log_;
+ this->public.set_level = (void(*)(sys_logger_t*,debug_t,level_t))set_level;
this->public.destroy = (void(*)(sys_logger_t*))destroy;
/* private variables */
this->facility = facility;
- set_level(this, SIG_ANY, LEVEL_SILENT);
+ set_level(this, DBG_ANY, LEVEL_SILENT);
return &this->public;
}
diff --git a/src/charon/bus/listeners/sys_logger.h b/src/charon/bus/listeners/sys_logger.h
index 0aade375a..08cf4dd63 100644
--- a/src/charon/bus/listeners/sys_logger.h
+++ b/src/charon/bus/listeners/sys_logger.h
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: sys_logger.h 3589 2008-03-13 14:14:44Z martin $
+ * $Id: sys_logger.h 4434 2008-10-14 08:52:13Z martin $
*/
/**
@@ -30,22 +30,22 @@ typedef struct sys_logger_t sys_logger_t;
#include <bus/bus.h>
/**
- * Logger for syslog which implements bus_listener_t.
+ * Logger for syslog which implements listener_t.
*/
struct sys_logger_t {
/**
- * Implements the bus_listener_t interface.
+ * Implements the listener_t interface.
*/
- bus_listener_t listener;
+ listener_t listener;
/**
- * Set the loglevel for a signal type.
+ * Set the loglevel for a debug group.
*
- * @param singal type of signal
- * @param level max level to log
+ * @param group debug group to set
+ * @param level max level to log (0..4)
*/
- void (*set_level) (sys_logger_t *this, signal_t signal, level_t level);
+ void (*set_level) (sys_logger_t *this, debug_t group, level_t level);
/**
* Destroys a sys_logger_t object.
diff --git a/src/charon/config/backend_manager.c b/src/charon/config/backend_manager.c
index c2b408ca9..3f92ee96a 100644
--- a/src/charon/config/backend_manager.c
+++ b/src/charon/config/backend_manager.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: backend_manager.c 4134 2008-07-01 11:10:37Z martin $
+ * $Id: backend_manager.c 4610 2008-11-11 06:19:37Z andreas $
*/
#include "backend_manager.h"
@@ -175,7 +175,7 @@ static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this,
data->me = me;
data->other = other;
- DBG2(DBG_CFG, "looking for a config for %H...%H", me, other);
+ DBG2(DBG_CFG, "looking for an ike config for %H...%H", me, other);
this->mutex->lock(this->mutex);
enumerator = enumerator_create_nested(
@@ -188,8 +188,8 @@ static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this,
if (match)
{
DBG2(DBG_CFG, " candidate: %s...%s, prio %d",
- current->get_my_addr(current), current->get_other_addr(current),
- match);
+ current->get_my_addr(current),
+ current->get_other_addr(current), match);
if (match > best)
{
DESTROY_IF(found);
@@ -201,6 +201,11 @@ static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this,
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
+ if (found)
+ {
+ DBG2(DBG_CFG, "found matching ike config: %s...%s with prio %d",
+ found->get_my_addr(found), found->get_other_addr(found), best);
+ }
return found;
}
@@ -227,7 +232,7 @@ static peer_cfg_t *get_peer_cfg(private_backend_manager_t *this, host_t *me,
ike_cfg_match_t best_ike = MATCH_NONE;
peer_data_t *data;
- DBG2(DBG_CFG, "looking for a config for %H[%D]...%H[%D]",
+ DBG2(DBG_CFG, "looking for a peer config for %H[%D]...%H[%D]",
me, my_id, other, other_id);
data = malloc_thing(peer_data_t);
@@ -262,7 +267,7 @@ static peer_cfg_t *get_peer_cfg(private_backend_manager_t *this, host_t *me,
if (m1 && m2 && match_ike &&
auth->complies(auth, current->get_auth(current)))
{
- DBG2(DBG_CFG, " candidate '%s': %D...%D, prio %d.%d",
+ DBG2(DBG_CFG, " candidate \"%s\": %D...%D with prio %d.%d",
current->get_name(current), my_cand, other_cand,
match_peer, match_ike);
if (match_peer >= best_peer && match_ike > best_ike)
@@ -277,7 +282,7 @@ static peer_cfg_t *get_peer_cfg(private_backend_manager_t *this, host_t *me,
}
if (found)
{
- DBG1(DBG_CFG, "found matching config \"%s\": %D...%D, prio %d.%d",
+ DBG1(DBG_CFG, "found matching peer config \"%s\": %D...%D with prio %d.%d",
found->get_name(found), found->get_my_id(found),
found->get_other_id(found), best_peer, best_ike);
}
diff --git a/src/charon/config/child_cfg.c b/src/charon/config/child_cfg.c
index 24242345b..ab083b212 100644
--- a/src/charon/config/child_cfg.c
+++ b/src/charon/config/child_cfg.c
@@ -14,7 +14,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: child_cfg.c 4358 2008-09-25 13:56:23Z tobias $
+ * $Id: child_cfg.c 4611 2008-11-11 06:29:25Z andreas $
*/
#include "child_cfg.h"
@@ -118,10 +118,20 @@ struct private_child_cfg_t {
* enable IPComp
*/
bool use_ipcomp;
+
+ /**
+ * set up IPsec transport SA in MIPv6 proxy mode
+ */
+ bool proxy_mode;
+
+ /**
+ * enable installation and removal of kernel IPsec policies
+ */
+ bool install_policy;
};
/**
- * Implementation of child_cfg_t.get_name
+ * Implementation of child_cfg_t.get_name.
*/
static char *get_name(private_child_cfg_t *this)
{
@@ -129,7 +139,7 @@ static char *get_name(private_child_cfg_t *this)
}
/**
- * Implementation of child_cfg_t.add_proposal
+ * Implementation of child_cfg_t.add_proposal.
*/
static void add_proposal(private_child_cfg_t *this, proposal_t *proposal)
{
@@ -137,7 +147,7 @@ static void add_proposal(private_child_cfg_t *this, proposal_t *proposal)
}
/**
- * Implementation of child_cfg_t.get_proposals
+ * Implementation of child_cfg_t.get_proposals.
*/
static linked_list_t* get_proposals(private_child_cfg_t *this, bool strip_dh)
{
@@ -161,7 +171,7 @@ static linked_list_t* get_proposals(private_child_cfg_t *this, bool strip_dh)
}
/**
- * Implementation of child_cfg_t.get_name
+ * Implementation of child_cfg_t.select_proposal.
*/
static proposal_t* select_proposal(private_child_cfg_t*this,
linked_list_t *proposals, bool strip_dh)
@@ -210,7 +220,7 @@ static proposal_t* select_proposal(private_child_cfg_t*this,
}
/**
- * Implementation of child_cfg_t.get_name
+ * Implementation of child_cfg_t.add_traffic_selector.
*/
static void add_traffic_selector(private_child_cfg_t *this, bool local,
traffic_selector_t *ts)
@@ -226,7 +236,7 @@ static void add_traffic_selector(private_child_cfg_t *this, bool local,
}
/**
- * Implementation of child_cfg_t.get_name
+ * Implementation of child_cfg_t.get_traffic_selectors.
*/
static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool local,
linked_list_t *supplied,
@@ -337,7 +347,36 @@ static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool loca
}
/**
- * Implementation of child_cfg_t.get_name
+ * Implementation of child_cfg_t.equal_traffic_selectors.
+ */
+bool equal_traffic_selectors(private_child_cfg_t *this, bool local,
+ linked_list_t *ts_list, host_t *host)
+{
+ linked_list_t *this_list;
+ traffic_selector_t *this_ts, *ts;
+ bool result;
+
+ this_list = (local) ? this->my_ts : this->other_ts;
+
+ /* currently equality is established for single traffic selectors only */
+ if (this_list->get_count(this_list) != 1 || ts_list->get_count(ts_list) != 1)
+ {
+ return FALSE;
+ }
+
+ this_list->get_first(this_list, (void**)&this_ts);
+ this_ts = this_ts->clone(this_ts);
+ this_ts->set_address(this_ts, host);
+ ts_list->get_first(ts_list, (void**)&ts);
+
+ result = ts->equals(ts, this_ts);
+
+ this_ts->destroy(this_ts);
+ return result;
+}
+
+/**
+ * Implementation of child_cfg_t.get_updown.
*/
static char* get_updown(private_child_cfg_t *this)
{
@@ -345,7 +384,7 @@ static char* get_updown(private_child_cfg_t *this)
}
/**
- * Implementation of child_cfg_t.get_name
+ * Implementation of child_cfg_t.get_hostaccess.
*/
static bool get_hostaccess(private_child_cfg_t *this)
{
@@ -353,7 +392,7 @@ static bool get_hostaccess(private_child_cfg_t *this)
}
/**
- * Implementation of child_cfg_t.get_name
+ * Implementation of child_cfg_t.get_lifetime.
*/
static u_int32_t get_lifetime(private_child_cfg_t *this, bool rekey)
{
@@ -369,7 +408,7 @@ static u_int32_t get_lifetime(private_child_cfg_t *this, bool rekey)
}
/**
- * Implementation of child_cfg_t.get_mode
+ * Implementation of child_cfg_t.get_mode.
*/
static ipsec_mode_t get_mode(private_child_cfg_t *this)
{
@@ -377,7 +416,7 @@ static ipsec_mode_t get_mode(private_child_cfg_t *this)
}
/**
- * Implementation of child_cfg_t.get_dpd_action
+ * Implementation of child_cfg_t.get_dpd_action.
*/
static action_t get_dpd_action(private_child_cfg_t *this)
{
@@ -385,7 +424,7 @@ static action_t get_dpd_action(private_child_cfg_t *this)
}
/**
- * Implementation of child_cfg_t.get_close_action
+ * Implementation of child_cfg_t.get_close_action.
*/
static action_t get_close_action(private_child_cfg_t *this)
{
@@ -422,7 +461,33 @@ static bool use_ipcomp(private_child_cfg_t *this)
}
/**
- * Implementation of child_cfg_t.get_name
+ * Implementation of child_cfg_t.set_mipv6_options.
+ */
+static void set_mipv6_options(private_child_cfg_t *this, bool proxy_mode,
+ bool install_policy)
+{
+ this->proxy_mode = proxy_mode;
+ this->install_policy = install_policy;
+}
+
+/**
+ * Implementation of child_cfg_t.use_proxy_mode.
+ */
+static bool use_proxy_mode(private_child_cfg_t *this)
+{
+ return this->proxy_mode;
+}
+
+/**
+ * Implementation of child_cfg_t.install_policy.
+ */
+static bool install_policy(private_child_cfg_t *this)
+{
+ return this->install_policy;
+}
+
+/**
+ * Implementation of child_cfg_t.get_ref.
*/
static child_cfg_t* get_ref(private_child_cfg_t *this)
{
@@ -462,6 +527,7 @@ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
this->public.get_name = (char* (*) (child_cfg_t*))get_name;
this->public.add_traffic_selector = (void (*)(child_cfg_t*,bool,traffic_selector_t*))add_traffic_selector;
this->public.get_traffic_selectors = (linked_list_t*(*)(child_cfg_t*,bool,linked_list_t*,host_t*))get_traffic_selectors;
+ this->public.equal_traffic_selectors = (bool (*)(child_cfg_t*,bool,linked_list_t*,host_t*))equal_traffic_selectors;
this->public.add_proposal = (void (*) (child_cfg_t*,proposal_t*))add_proposal;
this->public.get_proposals = (linked_list_t* (*) (child_cfg_t*,bool))get_proposals;
this->public.select_proposal = (proposal_t* (*) (child_cfg_t*,linked_list_t*,bool))select_proposal;
@@ -472,7 +538,10 @@ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
this->public.get_close_action = (action_t (*) (child_cfg_t *))get_close_action;
this->public.get_lifetime = (u_int32_t (*) (child_cfg_t *,bool))get_lifetime;
this->public.get_dh_group = (diffie_hellman_group_t(*)(child_cfg_t*)) get_dh_group;
+ this->public.set_mipv6_options = (void (*) (child_cfg_t*,bool,bool))set_mipv6_options;
this->public.use_ipcomp = (bool (*) (child_cfg_t *))use_ipcomp;
+ this->public.use_proxy_mode = (bool (*) (child_cfg_t *))use_proxy_mode;
+ this->public.install_policy = (bool (*) (child_cfg_t *))install_policy;
this->public.get_ref = (child_cfg_t* (*) (child_cfg_t*))get_ref;
this->public.destroy = (void (*) (child_cfg_t*))destroy;
@@ -486,6 +555,8 @@ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
this->dpd_action = dpd_action;
this->close_action = close_action;
this->use_ipcomp = ipcomp;
+ this->proxy_mode = FALSE;
+ this->install_policy = TRUE;
this->refcount = 1;
this->proposals = linked_list_create();
this->my_ts = linked_list_create();
diff --git a/src/charon/config/child_cfg.h b/src/charon/config/child_cfg.h
index 83d6cafe6..787324dca 100644
--- a/src/charon/config/child_cfg.h
+++ b/src/charon/config/child_cfg.h
@@ -14,7 +14,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: child_cfg.h 4358 2008-09-25 13:56:23Z tobias $
+ * $Id: child_cfg.h 4611 2008-11-11 06:29:25Z andreas $
*/
/**
@@ -154,6 +154,17 @@ struct child_cfg_t {
host_t *host);
/**
+ * Checks [single] traffic selectors for equality
+ *
+ * @param local TRUE for TS on local side, FALSE for remote
+ * @param ts list with single traffic selector to compare with
+ * @param host address to use for narrowing "dynamic" TS', or NULL
+ * @return TRUE if TS are equal, FALSE otherwise
+ */
+ bool (*equal_traffic_selectors)(child_cfg_t *this, bool local,
+ linked_list_t *ts_list, host_t *host);
+
+ /**
* Get the updown script to run for the CHILD_SA.
*
* @return path to updown script
@@ -219,6 +230,31 @@ struct child_cfg_t {
* FALSE, otherwise
*/
bool (*use_ipcomp)(child_cfg_t *this);
+
+ /**
+ * Sets two options needed for Mobile IPv6 interoperability
+ *
+ * @proxy_mode use IPsec transport proxy mode (default FALSE)
+ * @install_policy install IPsec kernel policies (default TRUE)
+ */
+ void (*set_mipv6_options)(child_cfg_t *this, bool proxy_mod,
+ bool install_policy);
+
+ /**
+ * Check whether IPsec transport SA should be set up in proxy mode
+ *
+ * @return TRUE, if proxy mode should be used
+ * FALSE, otherwise
+ */
+ bool (*use_proxy_mode)(child_cfg_t *this);
+
+ /**
+ * Check whether IPsec policies should be installed in the kernel
+ *
+ * @return TRUE, if IPsec kernel policies should be installed
+ * FALSE, otherwise
+ */
+ bool (*install_policy)(child_cfg_t *this);
/**
* Increase the reference count.
@@ -261,7 +297,6 @@ struct child_cfg_t {
child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
u_int32_t rekeytime, u_int32_t jitter,
char *updown, bool hostaccess, ipsec_mode_t mode,
- action_t dpd_action, action_t close_action,
- bool ipcomp);
+ action_t dpd_action, action_t close_action, bool ipcomp);
#endif /* CHILD_CFG_H_ @} */
diff --git a/src/charon/config/peer_cfg.c b/src/charon/config/peer_cfg.c
index 04f323128..9cbca040d 100644
--- a/src/charon/config/peer_cfg.c
+++ b/src/charon/config/peer_cfg.c
@@ -14,14 +14,16 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: peer_cfg.c 4276 2008-08-22 10:44:51Z martin $
+ * $Id: peer_cfg.c 4612 2008-11-11 06:37:37Z andreas $
*/
#include <string.h>
-#include <pthread.h>
#include "peer_cfg.h"
+#include <daemon.h>
+
+#include <utils/mutex.h>
#include <utils/linked_list.h>
#include <utils/identification.h>
@@ -77,7 +79,7 @@ struct private_peer_cfg_t {
/**
* mutex to lock access to list of child_cfgs
*/
- pthread_mutex_t mutex;
+ mutex_t *mutex;
/**
* id to use to identify us
@@ -197,9 +199,9 @@ static ike_cfg_t* get_ike_cfg(private_peer_cfg_t *this)
*/
static void add_child_cfg(private_peer_cfg_t *this, child_cfg_t *child_cfg)
{
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
this->child_cfgs->insert_last(this->child_cfgs, child_cfg);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
}
/**
@@ -207,9 +209,9 @@ static void add_child_cfg(private_peer_cfg_t *this, child_cfg_t *child_cfg)
*/
static void remove_child_cfg(private_peer_cfg_t *this, enumerator_t *enumerator)
{
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
this->child_cfgs->remove_at(this->child_cfgs, enumerator);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
}
/**
@@ -219,25 +221,29 @@ static enumerator_t* create_child_cfg_enumerator(private_peer_cfg_t *this)
{
enumerator_t *enumerator;
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
enumerator = this->child_cfgs->create_enumerator(this->child_cfgs);
return enumerator_create_cleaner(enumerator,
- (void*)pthread_mutex_unlock, &this->mutex);
+ (void*)this->mutex->unlock, this->mutex);
}
/**
* Check if child_cfg contains traffic selectors
*/
-static bool contains_ts(child_cfg_t *child, bool mine, linked_list_t *ts,
+static int contains_ts(child_cfg_t *child, bool mine, linked_list_t *ts,
host_t *host)
{
linked_list_t *selected;
- bool contains = FALSE;
+ int prio;
+ if (child->equal_traffic_selectors(child, mine, ts, host))
+ {
+ return 2;
+ }
selected = child->get_traffic_selectors(child, mine, ts, host);
- contains = selected->get_count(selected);
+ prio = selected->get_count(selected) ? 1 : 0;
selected->destroy_offset(selected, offsetof(traffic_selector_t, destroy));
- return contains;
+ return prio;
}
/**
@@ -250,18 +256,33 @@ static child_cfg_t* select_child_cfg(private_peer_cfg_t *this,
{
child_cfg_t *current, *found = NULL;
enumerator_t *enumerator;
-
+ int best = 0;
+
+ DBG2(DBG_CFG, "looking for a child config for %#R=== %#R", my_ts, other_ts);
enumerator = create_child_cfg_enumerator(this);
while (enumerator->enumerate(enumerator, &current))
{
- if (contains_ts(current, TRUE, my_ts, my_host) &&
- contains_ts(current, FALSE, other_ts, other_host))
+ int prio = contains_ts(current, TRUE, my_ts, my_host) +
+ contains_ts(current, FALSE, other_ts, other_host);
+
+ if (prio)
{
- found = current->get_ref(current);
- break;
+ DBG2(DBG_CFG, " candidate \"%s\" with prio %d",
+ current->get_name(current), prio);
+ if (prio > best)
+ {
+ best = prio;
+ DESTROY_IF(found);
+ found = current->get_ref(current);
+ }
}
}
enumerator->destroy(enumerator);
+ if (found)
+ {
+ DBG2(DBG_CFG, "found matching child config \"%s\" with prio %d",
+ found->get_name(found), best);
+ }
return found;
}
@@ -480,6 +501,7 @@ static void destroy(private_peer_cfg_t *this)
DESTROY_IF(this->mediated_by);
DESTROY_IF(this->peer_id);
#endif /* ME */
+ this->mutex->destroy(this->mutex);
free(this->name);
free(this->pool);
free(this);
@@ -536,7 +558,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
this->ike_version = ike_version;
this->ike_cfg = ike_cfg;
this->child_cfgs = linked_list_create();
- pthread_mutex_init(&this->mutex, NULL);
+ this->mutex = mutex_create(MUTEX_DEFAULT);
this->my_id = my_id;
this->other_id = other_id;
this->cert_policy = cert_policy;
diff --git a/src/charon/config/proposal.c b/src/charon/config/proposal.c
index b1c049fe8..202dc913a 100644
--- a/src/charon/config/proposal.c
+++ b/src/charon/config/proposal.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: proposal.c 4390 2008-10-08 12:57:11Z martin $
+ * $Id: proposal.c 4635 2008-11-12 08:27:48Z martin $
*/
#include <string.h>
diff --git a/src/charon/config/traffic_selector.c b/src/charon/config/traffic_selector.c
index 63172f855..d4235c32a 100644
--- a/src/charon/config/traffic_selector.c
+++ b/src/charon/config/traffic_selector.c
@@ -14,7 +14,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: traffic_selector.c 4199 2008-07-21 19:08:03Z andreas $
+ * $Id: traffic_selector.c 4639 2008-11-12 15:09:24Z martin $
*/
#include <arpa/inet.h>
@@ -134,8 +134,9 @@ static u_int8_t calc_netbits(private_traffic_selector_t *this)
int byte, bit;
size_t size = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
- /* go trough all bits of the addresses, begging in the front.
- * As longer as they equal, the subnet gets larger */
+ /* go trough all bits of the addresses, beginning in the front.
+ * as long as they are equal, the subnet gets larger
+ */
for (byte = 0; byte < size; byte++)
{
for (bit = 7; bit >= 0; bit--)
@@ -405,26 +406,15 @@ static bool equals(private_traffic_selector_t *this, private_traffic_selector_t
*/
static chunk_t get_from_address(private_traffic_selector_t *this)
{
- chunk_t from = chunk_empty;
-
switch (this->type)
{
case TS_IPV4_ADDR_RANGE:
- {
- from.len = sizeof(this->from4);
- from.ptr = malloc(from.len);
- memcpy(from.ptr, this->from4, from.len);
- break;
- }
+ return chunk_create(this->from, sizeof(this->from4));
case TS_IPV6_ADDR_RANGE:
- {
- from.len = sizeof(this->from6);
- from.ptr = malloc(from.len);
- memcpy(from.ptr, this->from6, from.len);
- break;
- }
+ return chunk_create(this->from, sizeof(this->from6));
+ default:
+ return chunk_empty;
}
- return from;
}
/**
@@ -432,26 +422,15 @@ static chunk_t get_from_address(private_traffic_selector_t *this)
*/
static chunk_t get_to_address(private_traffic_selector_t *this)
{
- chunk_t to = chunk_empty;
-
switch (this->type)
{
case TS_IPV4_ADDR_RANGE:
- {
- to.len = sizeof(this->to4);
- to.ptr = malloc(to.len);
- memcpy(to.ptr, this->to4, to.len);
- break;
- }
+ return chunk_create(this->to, sizeof(this->to4));
case TS_IPV6_ADDR_RANGE:
- {
- to.len = sizeof(this->to6);
- to.ptr = malloc(to.len);
- memcpy(to.ptr, this->to6, to.len);
- break;
- }
+ return chunk_create(this->to, sizeof(this->to6));
+ default:
+ return chunk_empty;
}
- return to;
}
/**
@@ -525,6 +504,14 @@ static bool is_host(private_traffic_selector_t *this, host_t *host)
}
/**
+ * Implementation of traffic_selector_t.is_dynamic
+ */
+static bool is_dynamic(private_traffic_selector_t *this)
+{
+ return this->dynamic;
+}
+
+/**
* Implements traffic_selector_t.set_address.
*/
static void set_address(private_traffic_selector_t *this, host_t *host)
@@ -583,6 +570,60 @@ static bool includes(private_traffic_selector_t *this, host_t *host)
}
/**
+ * Implements traffic_selector_t.to_subnet.
+ */
+static void to_subnet(private_traffic_selector_t *this, host_t **net, u_int8_t *mask)
+{
+ /* there is no way to do this cleanly, as the address range may
+ * be anything else but a subnet. We use from_addr as subnet
+ * and try to calculate a usable subnet mask.
+ */
+ int family, byte;
+ u_int16_t port = 0;
+ chunk_t net_chunk;
+
+ *mask = calc_netbits(this);
+
+ switch (this->type)
+ {
+ case TS_IPV4_ADDR_RANGE:
+ {
+ family = AF_INET;
+ net_chunk.len = sizeof(this->from4);
+ break;
+ }
+ case TS_IPV6_ADDR_RANGE:
+ {
+ family = AF_INET6;
+ net_chunk.len = sizeof(this->from6);
+ break;
+ }
+ default:
+ {
+ /* unreachable */
+ return;
+ }
+ }
+
+ net_chunk.ptr = malloc(net_chunk.len);
+ memcpy(net_chunk.ptr, this->from, net_chunk.len);
+
+ for (byte = net_chunk.len - 1; byte >= (*mask / 8); --byte)
+ {
+ int shift = (byte + 1) * 8 - *mask;
+ net_chunk.ptr[byte] = net_chunk.ptr[byte] & (0xFF << shift);
+ }
+
+ if (this->to_port == this->from_port)
+ {
+ port = this->to_port;
+ }
+
+ *net = host_create_from_chunk(family, net_chunk, port);
+ chunk_free(&net_chunk);
+}
+
+/**
* Implements traffic_selector_t.clone.
*/
static traffic_selector_t *clone_(private_traffic_selector_t *this)
@@ -814,9 +855,11 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol,
this->public.get_type = (ts_type_t(*)(traffic_selector_t*))get_type;
this->public.get_protocol = (u_int8_t(*)(traffic_selector_t*))get_protocol;
this->public.is_host = (bool(*)(traffic_selector_t*,host_t*))is_host;
+ this->public.is_dynamic = (bool(*)(traffic_selector_t*))is_dynamic;
this->public.is_contained_in = (bool(*)(traffic_selector_t*,traffic_selector_t*))is_contained_in;
this->public.includes = (bool(*)(traffic_selector_t*,host_t*))includes;
this->public.set_address = (void(*)(traffic_selector_t*,host_t*))set_address;
+ this->public.to_subnet = (void(*)(traffic_selector_t*,host_t**,u_int8_t*))to_subnet;
this->public.clone = (traffic_selector_t*(*)(traffic_selector_t*))clone_;
this->public.destroy = (void(*)(traffic_selector_t*))destroy;
diff --git a/src/charon/config/traffic_selector.h b/src/charon/config/traffic_selector.h
index 4b079a8e0..d97ffdea0 100644
--- a/src/charon/config/traffic_selector.h
+++ b/src/charon/config/traffic_selector.h
@@ -14,7 +14,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: traffic_selector.h 3658 2008-03-26 10:06:45Z martin $
+ * $Id: traffic_selector.h 4643 2008-11-12 22:57:46Z andreas $
*/
/**
@@ -92,7 +92,7 @@ struct traffic_selector_t {
/**
* Get starting address of this ts as a chunk.
*
- * Chunk is in network order gets allocated.
+ * Chunk is in network order and points to internal data.
*
* @return chunk containing the address
*/
@@ -101,7 +101,7 @@ struct traffic_selector_t {
/**
* Get ending address of this ts as a chunk.
*
- * Chunk is in network order gets allocated.
+ * Chunk is in network order and points to internal data.
*
* @return chunk containing the address
*/
@@ -155,6 +155,13 @@ struct traffic_selector_t {
bool (*is_host) (traffic_selector_t *this, host_t* host);
/**
+ * Check if a traffic selector has been created by create_dynamic().
+ *
+ * @return TRUE if TS is dynamic
+ */
+ bool (*is_dynamic)(traffic_selector_t *this);
+
+ /**
* Update the address of a traffic selector.
*
* Update the address range of a traffic selector, if it is
@@ -168,7 +175,7 @@ struct traffic_selector_t {
* Compare two traffic selectors for equality.
*
* @param other ts to compare with this
- * @return pointer to a string.
+ * @return TRUE if equal, FALSE otherwise
*/
bool (*equals) (traffic_selector_t *this, traffic_selector_t *other);
@@ -191,6 +198,17 @@ struct traffic_selector_t {
bool (*includes) (traffic_selector_t *this, host_t *host);
/**
+ * Convert a traffic selector address range to a subnet
+ * and its net mask.
+ * If from and to ports of this traffic selector are equal,
+ * the port of the returned host_t is set to that port.
+ *
+ * @param net converted subnet (has to be freed)
+ * @param mask converted net mask
+ */
+ void (*to_subnet) (traffic_selector_t *this, host_t **net, u_int8_t *mask);
+
+ /**
* Destroys the ts object
*/
void (*destroy) (traffic_selector_t *this);
@@ -225,7 +243,7 @@ traffic_selector_t *traffic_selector_create_from_string(
* @param type type of following addresses, such as TS_IPV4_ADDR_RANGE
* @param from_address start of address range, network order
* @param from_port port number, host order
- * @param to_address end of address range as string, network
+ * @param to_address end of address range, network order
* @param to_port port number, host order
* @return traffic_selector_t object
*/
diff --git a/src/charon/control/controller.c b/src/charon/control/controller.c
index c124f439a..ed52cb0d6 100644
--- a/src/charon/control/controller.c
+++ b/src/charon/control/controller.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: controller.c 4192 2008-07-18 15:51:40Z martin $
+ * $Id: controller.c 4434 2008-10-14 08:52:13Z martin $
*/
#include "controller.h"
@@ -27,7 +27,7 @@
typedef struct private_controller_t private_controller_t;
-typedef struct interface_bus_listener_t interface_bus_listener_t;
+typedef struct interface_listener_t interface_listener_t;
/**
* Private data of an stroke_t object.
@@ -40,16 +40,15 @@ struct private_controller_t {
controller_t public;
};
-
/**
- * helper struct to map bus listener callbacks to interface callbacks
+ * helper struct to map listener callbacks to interface callbacks
*/
-struct interface_bus_listener_t {
+struct interface_listener_t {
/**
* public bus listener interface
*/
- bus_listener_t public;
+ listener_t public;
/**
* status of the operation, return to method callers
@@ -57,11 +56,6 @@ struct interface_bus_listener_t {
status_t status;
/**
- * IKE SA to filter log output
- */
- ike_sa_t *ike_sa;
-
- /**
* interface callback (listener gets redirected to here)
*/
controller_cb_t callback;
@@ -82,6 +76,16 @@ struct interface_bus_listener_t {
peer_cfg_t *peer_cfg;
/**
+ * IKE_SA to handle
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * CHILD_SA to handle
+ */
+ child_sa_t *child_sa;
+
+ /**
* unique ID, used for various methods
*/
u_int32_t id;
@@ -102,38 +106,88 @@ struct interface_job_t {
/**
* associated listener
*/
- interface_bus_listener_t listener;
+ interface_listener_t listener;
};
/**
- * Implementation of controller_t.create_ike_sa_iterator.
+ * listener log function
*/
-static enumerator_t* create_ike_sa_enumerator(controller_t *this)
+static bool listener_log(interface_listener_t *this, debug_t group,
+ level_t level, int thread, ike_sa_t *ike_sa,
+ char* format, va_list args)
{
- return charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager);
+ if (this->ike_sa == ike_sa)
+ {
+ if (!this->callback(this->param, group, level, ike_sa, format, args))
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
}
/**
- * listener function for initiate
+ * Implementation of listener_t.ike_state_change
*/
-static bool initiate_listener(interface_bus_listener_t *this, signal_t signal,
- level_t level, int thread, ike_sa_t *ike_sa,
- void* data, char* format, va_list args)
+static bool listener_ike_state(interface_listener_t *this, ike_sa_t *ike_sa,
+ ike_sa_state_t state)
{
if (this->ike_sa == ike_sa)
{
- if (!this->callback(this->param, signal, level, ike_sa, data,
- format, args))
+ switch (state)
{
- return FALSE;
+#ifdef ME
+ case IKE_ESTABLISHED:
+ { /* mediation connections are complete without CHILD_SA */
+ peer_cfg_t *peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+
+ if (peer_cfg->is_mediation(peer_cfg))
+ {
+ this->status = SUCCESS;
+ return FALSE;
+ }
+ break;
+ }
+#endif /* ME */
+ case IKE_DESTROYING:
+ if (ike_sa->get_state(ike_sa) == IKE_DELETING)
+ { /* proper termination */
+ this->status = SUCCESS;
+ }
+ return FALSE;
+ default:
+ break;
}
- switch (signal)
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of listener_t.child_state_change
+ */
+static bool listener_child_state(interface_listener_t *this, ike_sa_t *ike_sa,
+ child_sa_t *child_sa, child_sa_state_t state)
+{
+ if (this->ike_sa == ike_sa)
+ {
+ switch (state)
{
- case CHD_UP_SUCCESS:
+ case CHILD_ROUTED:
+ case CHILD_INSTALLED:
this->status = SUCCESS;
return FALSE;
- case IKE_UP_FAILED:
- case CHD_UP_FAILED:
+ case CHILD_DESTROYING:
+ switch (child_sa->get_state(child_sa))
+ {
+ case CHILD_ROUTED:
+ /* has been unrouted */
+ case CHILD_DELETING:
+ /* proper delete */
+ this->status = SUCCESS;
+ break;
+ default:
+ break;
+ }
return FALSE;
default:
break;
@@ -143,12 +197,32 @@ static bool initiate_listener(interface_bus_listener_t *this, signal_t signal,
}
/**
+ * cleanup job if job is never executed
+ */
+static void recheckin(interface_job_t *job)
+{
+ if (job->listener.ike_sa)
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager,
+ job->listener.ike_sa);
+ }
+}
+
+/**
+ * Implementation of controller_t.create_ike_sa_iterator.
+ */
+static enumerator_t* create_ike_sa_enumerator(controller_t *this)
+{
+ return charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager);
+}
+
+/**
* execute function for initiate
*/
static status_t initiate_execute(interface_job_t *job)
{
ike_sa_t *ike_sa;
- interface_bus_listener_t *listener = &job->listener;
+ interface_listener_t *listener = &job->listener;
peer_cfg_t *peer_cfg = listener->peer_cfg;
ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
@@ -176,72 +250,41 @@ static status_t initiate(private_controller_t *this,
peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
controller_cb_t callback, void *param)
{
- interface_job_t job;
-
- job.listener.public.signal = (void*)initiate_listener;
- job.listener.ike_sa = NULL;
- job.listener.callback = callback;
- job.listener.param = param;
- job.listener.status = FAILED;
- job.listener.child_cfg = child_cfg;
- job.listener.peer_cfg = peer_cfg;
- job.public.execute = (void*)initiate_execute;
- job.public.destroy = nop;
-
+ interface_job_t job = {
+ .listener = {
+ .public = {
+ .log = (void*)listener_log,
+ .ike_state_change = (void*)listener_ike_state,
+ .child_state_change = (void*)listener_child_state,
+ },
+ .callback = callback,
+ .param = param,
+ .status = FAILED,
+ .child_cfg = child_cfg,
+ .peer_cfg = peer_cfg,
+ },
+ .public = {
+ .execute = (void*)initiate_execute,
+ .destroy = (void*)recheckin,
+ },
+ };
if (callback == NULL)
{
return initiate_execute(&job);
}
- charon->bus->listen(charon->bus, (bus_listener_t*)&job.listener, (job_t*)&job);
+ charon->bus->listen(charon->bus, &job.listener.public, (job_t*)&job);
return job.listener.status;
}
/**
- * listener function for terminate_ike
- */
-static bool terminate_ike_listener(interface_bus_listener_t *this, signal_t signal,
- level_t level, int thread, ike_sa_t *ike_sa,
- void* data, char* format, va_list args)
-{
- if (this->ike_sa == ike_sa)
- {
- if (!this->callback(this->param, signal, level, ike_sa,
- data, format, args))
- {
- return FALSE;
- }
- switch (signal)
- {
- case IKE_DOWN_SUCCESS:
- this->status = SUCCESS;
- return FALSE;
- case IKE_DOWN_FAILED:
- return FALSE;
- default:
- break;
- }
- }
- return TRUE;
-}
-
-/**
* execute function for terminate_ike
*/
static status_t terminate_ike_execute(interface_job_t *job)
{
- ike_sa_t *ike_sa;
- interface_bus_listener_t *listener = &job->listener;
-
- ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
- listener->id, FALSE);
- if (ike_sa == NULL)
- {
- SIG_IKE(DOWN_FAILED, "unable to terminate, IKE_SA with "
- "ID %d not found", listener->id);
- return NOT_FOUND;
- }
- listener->ike_sa = ike_sa;
+ interface_listener_t *listener = &job->listener;
+ ike_sa_t *ike_sa = listener->ike_sa;
+ charon->bus->set_sa(charon->bus, ike_sa);
if (ike_sa->delete(ike_sa) == DESTROY_ME)
{
return charon->ike_sa_manager->checkin_and_destroy(
@@ -256,79 +299,103 @@ static status_t terminate_ike_execute(interface_job_t *job)
static status_t terminate_ike(controller_t *this, u_int32_t unique_id,
controller_cb_t callback, void *param)
{
- interface_job_t job;
+ ike_sa_t *ike_sa;
+ interface_job_t job = {
+ .listener = {
+ .public = {
+ .log = (void*)listener_log,
+ .ike_state_change = (void*)listener_ike_state,
+ .child_state_change = (void*)listener_child_state,
+ },
+ .callback = callback,
+ .param = param,
+ .status = FAILED,
+ .id = unique_id,
+ },
+ .public = {
+ .execute = (void*)terminate_ike_execute,
+ .destroy = (void*)recheckin,
+ },
+ };
+
+ ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+ unique_id, FALSE);
+ if (ike_sa == NULL)
+ {
+ DBG1(DBG_IKE, "unable to terminate IKE_SA: ID %d not found", unique_id);
+ return NOT_FOUND;
+ }
+ job.listener.ike_sa = ike_sa;
- job.listener.public.signal = (void*)terminate_ike_listener;
- job.listener.ike_sa = NULL;
- job.listener.callback = callback;
- job.listener.param = param;
- job.listener.status = FAILED;
- job.listener.id = unique_id;
- job.public.execute = (void*)terminate_ike_execute;
- job.public.destroy = nop;
-
if (callback == NULL)
{
return terminate_ike_execute(&job);
}
- charon->bus->listen(charon->bus, (bus_listener_t*)&job.listener, (job_t*)&job);
+ charon->bus->listen(charon->bus, &job.listener.public, (job_t*)&job);
return job.listener.status;
}
+
/**
- * listener function for terminate_child
+ * execute function for terminate_child
*/
-static bool terminate_child_listener(interface_bus_listener_t *this, signal_t signal,
- level_t level, int thread, ike_sa_t *ike_sa,
- void* data, char* format, va_list args)
+static status_t terminate_child_execute(interface_job_t *job)
{
- if (this->ike_sa == ike_sa)
+ interface_listener_t *listener = &job->listener;
+ ike_sa_t *ike_sa = listener->ike_sa;
+ child_sa_t *child_sa = listener->child_sa;
+
+ charon->bus->set_sa(charon->bus, ike_sa);
+ if (ike_sa->delete_child_sa(ike_sa, child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE)) == DESTROY_ME)
{
- if (!this->callback(this->param, signal, level, ike_sa,
- data, format, args))
- {
- return FALSE;
- }
- switch (signal)
- {
- case CHD_DOWN_SUCCESS:
- case IKE_DOWN_SUCCESS:
- this->status = SUCCESS;
- return FALSE;
- case IKE_DOWN_FAILED:
- case CHD_DOWN_FAILED:
- return FALSE;
- default:
- break;
- }
+ return charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, ike_sa);
}
- return TRUE;
+ return charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
/**
- * execute function for terminate_child
+ * Implementation of controller_t.terminate_child.
*/
-static status_t terminate_child_execute(interface_job_t *job)
+static status_t terminate_child(controller_t *this, u_int32_t reqid,
+ controller_cb_t callback, void *param)
{
ike_sa_t *ike_sa;
child_sa_t *child_sa;
iterator_t *iterator;
- interface_bus_listener_t *listener = &job->listener;
+ interface_job_t job = {
+ .listener = {
+ .public = {
+ .log = (void*)listener_log,
+ .ike_state_change = (void*)listener_ike_state,
+ .child_state_change = (void*)listener_child_state,
+ },
+ .callback = callback,
+ .param = param,
+ .status = FAILED,
+ .id = reqid,
+ },
+ .public = {
+ .execute = (void*)terminate_child_execute,
+ .destroy = (void*)recheckin,
+ },
+ };
ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
- listener->id, TRUE);
+ reqid, TRUE);
if (ike_sa == NULL)
{
- SIG_CHD(DOWN_FAILED, NULL, "unable to terminate, CHILD_SA with "
- "ID %d not found", listener->id);
+ DBG1(DBG_IKE, "unable to terminate, CHILD_SA with ID %d not found",
+ reqid);
return NOT_FOUND;
}
- listener->ike_sa = ike_sa;
+ job.listener.ike_sa = ike_sa;
iterator = ike_sa->create_child_sa_iterator(ike_sa);
while (iterator->iterate(iterator, (void**)&child_sa))
{
if (child_sa->get_state(child_sa) != CHILD_ROUTED &&
- child_sa->get_reqid(child_sa) == listener->id)
+ child_sa->get_reqid(child_sa) == reqid)
{
break;
}
@@ -338,90 +405,30 @@ static status_t terminate_child_execute(interface_job_t *job)
if (child_sa == NULL)
{
- SIG_CHD(DOWN_FAILED, NULL, "unable to terminate, established "
- "CHILD_SA with ID %d not found", listener->id);
+ DBG1(DBG_IKE, "unable to terminate, established "
+ "CHILD_SA with ID %d not found", reqid);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
return NOT_FOUND;
}
-
- if (ike_sa->delete_child_sa(ike_sa, child_sa->get_protocol(child_sa),
- child_sa->get_spi(child_sa, TRUE)) == DESTROY_ME)
- {
- return charon->ike_sa_manager->checkin_and_destroy(
- charon->ike_sa_manager, ike_sa);
- }
- return charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
-}
-
-/**
- * Implementation of controller_t.terminate_child.
- */
-static status_t terminate_child(controller_t *this, u_int32_t reqid,
- controller_cb_t callback, void *param)
-{
- interface_job_t job;
-
- job.listener.public.signal = (void*)terminate_child_listener;
- job.listener.ike_sa = NULL;
- job.listener.callback = callback;
- job.listener.param = param;
- job.listener.status = FAILED;
- job.listener.id = reqid;
- job.public.execute = (void*)terminate_child_execute;
- job.public.destroy = nop;
+ job.listener.child_sa = child_sa;
if (callback == NULL)
{
return terminate_child_execute(&job);
}
- charon->bus->listen(charon->bus, (bus_listener_t*)&job.listener, (job_t*)&job);
+ charon->bus->listen(charon->bus, &job.listener.public, (job_t*)&job);
return job.listener.status;
}
/**
- * listener function for route
- */
-static bool route_listener(interface_bus_listener_t *this, signal_t signal,
- level_t level, int thread, ike_sa_t *ike_sa,
- void* data, char* format, va_list args)
-{
- if (this->ike_sa == ike_sa)
- {
- if (!this->callback(this->param, signal, level, ike_sa,
- data, format, args))
- {
- return FALSE;
- }
- switch (signal)
- {
- case CHD_ROUTE_SUCCESS:
- this->status = SUCCESS;
- return FALSE;
- case CHD_ROUTE_FAILED:
- return FALSE;
- default:
- break;
- }
- }
- return TRUE;
-}
-
-/**
* execute function for route
*/
static status_t route_execute(interface_job_t *job)
{
- ike_sa_t *ike_sa;
- interface_bus_listener_t *listener = &job->listener;
- peer_cfg_t *peer_cfg = listener->peer_cfg;
- ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
- peer_cfg);
- listener->ike_sa = ike_sa;
+ interface_listener_t *listener = &job->listener;
+ ike_sa_t *ike_sa = listener->ike_sa;
- if (ike_sa->get_peer_cfg(ike_sa) == NULL)
- {
- ike_sa->set_peer_cfg(ike_sa, peer_cfg);
- }
+ charon->bus->set_sa(charon->bus, ike_sa);
if (ike_sa->route(ike_sa, listener->child_cfg) == DESTROY_ME)
{
return charon->ike_sa_manager->checkin_and_destroy(
@@ -437,70 +444,49 @@ static status_t route(controller_t *this,
peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
controller_cb_t callback, void *param)
{
- interface_job_t job;
+ ike_sa_t *ike_sa;
+ interface_job_t job = {
+ .listener = {
+ .public = {
+ .log = (void*)listener_log,
+ .ike_state_change = (void*)listener_ike_state,
+ .child_state_change = (void*)listener_child_state,
+ },
+ .callback = callback,
+ .param = param,
+ .status = FAILED,
+ .peer_cfg = peer_cfg,
+ .child_cfg = child_cfg,
+ },
+ .public = {
+ .execute = (void*)route_execute,
+ .destroy = (void*)recheckin,
+ },
+ };
- job.listener.public.signal = (void*)route_listener;
- job.listener.ike_sa = NULL;
- job.listener.callback = callback;
- job.listener.param = param;
- job.listener.status = FAILED;
- job.listener.peer_cfg = peer_cfg;
- job.listener.child_cfg = child_cfg;
- job.public.execute = (void*)route_execute;
- job.public.destroy = nop;
-
+ ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
+ peer_cfg);
+ if (ike_sa->get_peer_cfg(ike_sa) == NULL)
+ {
+ ike_sa->set_peer_cfg(ike_sa, peer_cfg);
+ }
+ job.listener.ike_sa = ike_sa;
if (callback == NULL)
{
return route_execute(&job);
}
- charon->bus->listen(charon->bus, (bus_listener_t*)&job.listener, (job_t*)&job);
+ charon->bus->listen(charon->bus, &job.listener.public, (job_t*)&job);
return job.listener.status;
}
/**
- * listener function for unroute
- */
-static bool unroute_listener(interface_bus_listener_t *this, signal_t signal,
- level_t level, int thread, ike_sa_t *ike_sa,
- void* data, char* format, va_list args)
-{
- if (this->ike_sa == ike_sa)
- {
- if (!this->callback(this->param, signal, level, ike_sa,
- data, format, args))
- {
- return FALSE;
- }
- switch (signal)
- {
- case CHD_UNROUTE_SUCCESS:
- this->status = SUCCESS;
- return FALSE;
- case CHD_UNROUTE_FAILED:
- return FALSE;
- default:
- break;
- }
- }
- return TRUE;
-}
-/**
* execute function for unroute
*/
static status_t unroute_execute(interface_job_t *job)
{
- ike_sa_t *ike_sa;
- interface_bus_listener_t *listener = &job->listener;
+ interface_listener_t *listener = &job->listener;
+ ike_sa_t *ike_sa = listener->ike_sa;
- ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
- listener->id, TRUE);
- if (ike_sa == NULL)
- {
- SIG_CHD(DOWN_FAILED, NULL, "unable to unroute, CHILD_SA with "
- "ID %d not found", listener->id);
- return NOT_FOUND;
- }
- listener->ike_sa = ike_sa;
if (ike_sa->unroute(ike_sa, listener->id) == DESTROY_ME)
{
return charon->ike_sa_manager->checkin_and_destroy(
@@ -515,30 +501,47 @@ static status_t unroute_execute(interface_job_t *job)
static status_t unroute(controller_t *this, u_int32_t reqid,
controller_cb_t callback, void *param)
{
- interface_job_t job;
+ ike_sa_t *ike_sa;
+ interface_job_t job = {
+ .listener = {
+ .public = {
+ .log = (void*)listener_log,
+ .ike_state_change = (void*)listener_ike_state,
+ .child_state_change = (void*)listener_child_state,
+ },
+ .callback = callback,
+ .param = param,
+ .status = FAILED,
+ .id = reqid,
+ },
+ .public = {
+ .execute = (void*)unroute_execute,
+ .destroy = (void*)recheckin,
+ },
+ };
- job.listener.public.signal = (void*)unroute_listener;
- job.listener.ike_sa = NULL;
- job.listener.callback = callback;
- job.listener.param = param;
- job.listener.status = FAILED;
- job.listener.id = reqid;
- job.public.execute = (void*)unroute_execute;
- job.public.destroy = nop;
+ ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+ reqid, TRUE);
+ if (ike_sa == NULL)
+ {
+ DBG1(DBG_IKE, "unable to unroute, CHILD_SA with ID %d not found", reqid);
+ return NOT_FOUND;
+ }
+ job.listener.ike_sa = ike_sa;
if (callback == NULL)
{
return unroute_execute(&job);
}
- charon->bus->listen(charon->bus, (bus_listener_t*)&job.listener, (job_t*)&job);
+ charon->bus->listen(charon->bus, &job.listener.public, (job_t*)&job);
return job.listener.status;
}
/**
* See header
*/
-bool controller_cb_empty(void *param, signal_t signal, level_t level,
- ike_sa_t *ike_sa, void *data, char *format, va_list args)
+bool controller_cb_empty(void *param, debug_t group, level_t level,
+ ike_sa_t *ike_sa, char *format, va_list args)
{
return TRUE;
}
diff --git a/src/charon/control/controller.h b/src/charon/control/controller.h
index f40af0260..4609d7a8b 100644
--- a/src/charon/control/controller.h
+++ b/src/charon/control/controller.h
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: controller.h 4192 2008-07-18 15:51:40Z martin $
+ * $Id: controller.h 4624 2008-11-11 13:11:44Z tobias $
*/
/**
@@ -29,26 +29,24 @@
* callback to log things triggered by controller.
*
* @param param echoed parameter supplied when function invoked
- * @param signal type of signal
+ * @param group debugging group
* @param level verbosity level if log
* @param ike_sa associated IKE_SA, if any
* @param format printf like format string
* @param args list of arguments to use for format
* @return FALSE to return from invoked function
*/
-typedef bool(*controller_cb_t)(void* param, signal_t signal, level_t level,
- ike_sa_t* ike_sa, void *data,
- char* format, va_list args);
+typedef bool(*controller_cb_t)(void* param, debug_t group, level_t level,
+ ike_sa_t* ike_sa, char* format, va_list args);
/**
* Empty callback function for controller_t functions.
*
- * If you wan't to do a syncrhonous call, but don't need a callback, pass
+ * If you want to do a synchronous call, but don't need a callback, pass
* this function to the controllers methods.
*/
-bool controller_cb_empty(void *param, signal_t signal, level_t level,
- ike_sa_t *ike_sa, void *data,
- char *format, va_list args);
+bool controller_cb_empty(void *param, debug_t group, level_t level,
+ ike_sa_t *ike_sa, char *format, va_list args);
typedef struct controller_t controller_t;
@@ -59,7 +57,7 @@ typedef struct controller_t controller_t;
* evaluate the result of the operation by listening on the bus.
*
* Passing NULL as callback to the managers function calls them asynchronously.
- * If a callback is specified, they are called synchronoulsy. There is a default
+ * If a callback is specified, they are called synchronously. There is a default
* callback "controller_cb_empty" if you wan't to call a function
* synchronously, but don't need a callback.
*/
@@ -78,7 +76,7 @@ struct controller_t {
/**
* Initiate a CHILD_SA, and if required, an IKE_SA.
*
- * The inititate() function is synchronous and thus blocks until the
+ * The initiate() function is synchronous and thus blocks until the
* IKE_SA is established or failed. Because of this, the initiate() function
* contains a thread cancellation point.
*
diff --git a/src/charon/credentials/credential_manager.c b/src/charon/credentials/credential_manager.c
index b11cdc0df..309115280 100644
--- a/src/charon/credentials/credential_manager.c
+++ b/src/charon/credentials/credential_manager.c
@@ -12,16 +12,15 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: credential_manager.c 4317 2008-09-02 11:00:13Z martin $
+ * $Id: credential_manager.c 4591 2008-11-05 16:12:54Z martin $
*/
-/* some clibs need it for rwlocks */
-#define _GNU_SOURCE
#include <pthread.h>
#include "credential_manager.h"
#include <daemon.h>
+#include <utils/mutex.h>
#include <utils/linked_list.h>
#include <credentials/sets/cert_cache.h>
#include <credentials/sets/auth_info_wrapper.h>
@@ -68,7 +67,7 @@ struct private_credential_manager_t {
/**
* read-write lock to sets list
*/
- pthread_rwlock_t lock;
+ rwlock_t *lock;
};
/** data to pass to create_private_enumerator */
@@ -170,7 +169,7 @@ static enumerator_t *create_sets_enumerator(private_credential_manager_t *this)
*/
static void destroy_cert_data(cert_data_t *data)
{
- pthread_rwlock_unlock(&data->this->lock);
+ data->this->lock->unlock(data->this->lock);
free(data);
}
@@ -197,7 +196,7 @@ static enumerator_t *create_cert_enumerator(private_credential_manager_t *this,
data->id = id;
data->trusted = trusted;
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
return enumerator_create_nested(create_sets_enumerator(this),
(void*)create_cert, data,
(void*)destroy_cert_data);
@@ -229,7 +228,7 @@ static certificate_t *get_cert(private_credential_manager_t *this,
*/
static void destroy_cdp_data(cdp_data_t *data)
{
- pthread_rwlock_unlock(&data->this->lock);
+ data->this->lock->unlock(data->this->lock);
free(data);
}
@@ -251,7 +250,7 @@ static enumerator_t * create_cdp_enumerator(private_credential_manager_t *this,
data->type = type;
data->id = id;
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
return enumerator_create_nested(create_sets_enumerator(this),
(void*)create_cdp, data,
(void*)destroy_cdp_data);
@@ -262,7 +261,7 @@ static enumerator_t * create_cdp_enumerator(private_credential_manager_t *this,
*/
static void destroy_private_data(private_data_t *data)
{
- pthread_rwlock_unlock(&data->this->lock);
+ data->this->lock->unlock(data->this->lock);
free(data);
}
@@ -287,7 +286,7 @@ static enumerator_t* create_private_enumerator(
data->this = this;
data->type = key;
data->keyid = keyid;
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
return enumerator_create_nested(create_sets_enumerator(this),
(void*)create_private, data,
(void*)destroy_private_data);
@@ -316,7 +315,7 @@ static private_key_t *get_private_by_keyid(private_credential_manager_t *this,
*/
static void destroy_shared_data(shared_data_t *data)
{
- pthread_rwlock_unlock(&data->this->lock);
+ data->this->lock->unlock(data->this->lock);
free(data);
}
@@ -341,7 +340,7 @@ static enumerator_t *create_shared_enumerator(private_credential_manager_t *this
data->me = me;
data->other = other;
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
return enumerator_create_nested(create_sets_enumerator(this),
(void*)create_shared, data,
(void*)destroy_shared_data);
@@ -412,7 +411,7 @@ static void cache_cert(private_credential_manager_t *this, certificate_t *cert)
credential_set_t *set;
enumerator_t *enumerator;
- if (pthread_rwlock_trywrlock(&this->lock) == 0)
+ if (this->lock->try_write_lock(this->lock))
{
enumerator = this->sets->create_enumerator(this->sets);
while (enumerator->enumerate(enumerator, &set))
@@ -423,10 +422,10 @@ static void cache_cert(private_credential_manager_t *this, certificate_t *cert)
}
else
{ /* we can't cache now as other threads are active, queue for later */
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
this->cache_queue->insert_last(this->cache_queue, cert->get_ref(cert));
}
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
}
/**
@@ -439,7 +438,7 @@ static void cache_queue(private_credential_manager_t *this)
enumerator_t *enumerator;
if (this->cache_queue->get_count(this->cache_queue) > 0 &&
- pthread_rwlock_trywrlock(&this->lock) == 0)
+ this->lock->try_write_lock(this->lock))
{
while (this->cache_queue->remove_last(this->cache_queue,
(void**)&cert) == SUCCESS)
@@ -452,7 +451,7 @@ static void cache_queue(private_credential_manager_t *this)
enumerator->destroy(enumerator);
cert->destroy(cert);
}
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
}
}
@@ -1302,7 +1301,7 @@ static void public_destroy(public_enumerator_t *this)
remove_local_set(this->this, &this->wrapper->set);
this->wrapper->destroy(this->wrapper);
}
- pthread_rwlock_unlock(&this->this->lock);
+ this->this->lock->unlock(this->this->lock);
/* check for delayed certificate cache queue */
cache_queue(this->this);
@@ -1328,7 +1327,7 @@ static enumerator_t* create_public_enumerator(private_credential_manager_t *this
enumerator->wrapper = auth_info_wrapper_create(auth);
add_local_set(this, &enumerator->wrapper->set);
}
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
return &enumerator->public;
}
@@ -1525,9 +1524,9 @@ static void flush_cache(private_credential_manager_t *this,
static void add_set(private_credential_manager_t *this,
credential_set_t *set)
{
- pthread_rwlock_wrlock(&this->lock);
+ this->lock->write_lock(this->lock);
this->sets->insert_last(this->sets, set);
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
}
/**
@@ -1535,9 +1534,9 @@ static void add_set(private_credential_manager_t *this,
*/
static void remove_set(private_credential_manager_t *this, credential_set_t *set)
{
- pthread_rwlock_wrlock(&this->lock);
+ this->lock->write_lock(this->lock);
this->sets->remove(this->sets, set, NULL);
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
}
/**
@@ -1551,7 +1550,7 @@ static void destroy(private_credential_manager_t *this)
this->sets->destroy(this->sets);
pthread_key_delete(this->local_sets);
this->cache->destroy(this->cache);
- pthread_rwlock_destroy(&this->lock);
+ this->lock->destroy(this->lock);
free(this);
}
@@ -1580,7 +1579,7 @@ credential_manager_t *credential_manager_create()
this->cache = cert_cache_create();
this->cache_queue = linked_list_create();
this->sets->insert_first(this->sets, this->cache);
- pthread_rwlock_init(&this->lock, NULL);
+ this->lock = rwlock_create(RWLOCK_DEFAULT);
return &this->public;
}
diff --git a/src/charon/credentials/sets/cert_cache.c b/src/charon/credentials/sets/cert_cache.c
index 4a9a97149..79b5f0203 100644
--- a/src/charon/credentials/sets/cert_cache.c
+++ b/src/charon/credentials/sets/cert_cache.c
@@ -15,12 +15,12 @@
* $Id$
*/
-#define _GNU_SOURCE
-#include <pthread.h>
-
#include "cert_cache.h"
+#include <time.h>
+
#include <daemon.h>
+#include <utils/mutex.h>
#include <utils/linked_list.h>
#define CACHE_SIZE 30
@@ -56,7 +56,7 @@ struct private_cert_cache_t {
/**
* read-write lock to sets list
*/
- pthread_rwlock_t lock;
+ rwlock_t *lock;
};
/**
@@ -90,7 +90,7 @@ static void check_cache(private_cert_cache_t *this)
{
this->check_required = TRUE;
}
- else if (pthread_rwlock_trywrlock(&this->lock) == 0)
+ else if (this->lock->try_write_lock(this->lock))
{ /* never blocks, only done if lock is available */
while (this->relations->get_count(this->relations) > CACHE_SIZE)
{
@@ -110,7 +110,7 @@ static void check_cache(private_cert_cache_t *this)
relation_destroy(oldest);
}
this->check_required = FALSE;
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
}
}
@@ -124,7 +124,7 @@ static bool issued_by(private_cert_cache_t *this,
enumerator_t *enumerator;
/* lookup cache */
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
enumerator = this->relations->create_enumerator(this->relations);
while (enumerator->enumerate(enumerator, &current))
{
@@ -149,7 +149,7 @@ static bool issued_by(private_cert_cache_t *this,
}
}
enumerator->destroy(enumerator);
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
if (found)
{
return TRUE;
@@ -233,7 +233,7 @@ static bool certs_filter(cert_data_t *data, relation_t **in, certificate_t **out
static void certs_destroy(cert_data_t *data)
{
ref_put(&data->this->enumerating);
- pthread_rwlock_unlock(&data->this->lock);
+ data->this->lock->unlock(data->this->lock);
if (data->this->check_required)
{
check_cache(data->this);
@@ -260,7 +260,7 @@ static enumerator_t *create_enumerator(private_cert_cache_t *this,
data->id = id;
data->this = this;
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
ref_get(&this->enumerating);
return enumerator_create_filter(
this->relations->create_enumerator(this->relations),
@@ -275,7 +275,7 @@ static void flush(private_cert_cache_t *this, certificate_type_t type)
enumerator_t *enumerator;
relation_t *relation;
- pthread_rwlock_wrlock(&this->lock);
+ this->lock->write_lock(this->lock);
enumerator = this->relations->create_enumerator(this->relations);
while (enumerator->enumerate(enumerator, &relation))
{
@@ -287,7 +287,7 @@ static void flush(private_cert_cache_t *this, certificate_type_t type)
}
}
enumerator->destroy(enumerator);
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
}
/**
@@ -296,7 +296,7 @@ static void flush(private_cert_cache_t *this, certificate_type_t type)
static void destroy(private_cert_cache_t *this)
{
this->relations->destroy_function(this->relations, (void*)relation_destroy);
- pthread_rwlock_destroy(&this->lock);
+ this->lock->destroy(this->lock);
free(this);
}
@@ -319,7 +319,7 @@ cert_cache_t *cert_cache_create()
this->relations = linked_list_create();
this->enumerating = 0;
this->check_required = FALSE;
- pthread_rwlock_init(&this->lock, NULL);
+ this->lock = rwlock_create(RWLOCK_DEFAULT);
return &this->public;
}
diff --git a/src/charon/daemon.c b/src/charon/daemon.c
index 065f7d701..b9f173901 100644
--- a/src/charon/daemon.c
+++ b/src/charon/daemon.c
@@ -16,11 +16,6 @@
* for more details.
*/
-#ifdef HAVE_DLADDR
-# define _GNU_SOURCE
-# include <dlfcn.h>
-#endif /* HAVE_DLADDR */
-
#include <stdio.h>
#include <sys/prctl.h>
#include <signal.h>
@@ -34,9 +29,6 @@
#include <errno.h>
#include <pwd.h>
#include <grp.h>
-#ifdef HAVE_BACKTRACE
-# include <execinfo.h>
-#endif /* HAVE_BACKTRACE */
#ifdef CAPABILITIES
#include <sys/capability.h>
#endif /* CAPABILITIES */
@@ -44,6 +36,7 @@
#include "daemon.h"
#include <library.h>
+#include <utils/backtrace.h>
#include <config/traffic_selector.h>
#include <config/proposal.h>
@@ -99,7 +92,7 @@ static void dbg_bus(int level, char *fmt, ...)
va_list args;
va_start(args, fmt);
- charon->bus->vsignal(charon->bus, DBG_LIB, level, NULL, fmt, args);
+ charon->bus->vlog(charon->bus, DBG_LIB, level, fmt, args);
va_end(args);
}
@@ -212,9 +205,10 @@ static void destroy(private_daemon_t *this)
/* rehook library logging, shutdown logging */
dbg = dbg_stderr;
DESTROY_IF(this->public.bus);
- DESTROY_IF(this->public.outlog);
- DESTROY_IF(this->public.syslog);
- DESTROY_IF(this->public.authlog);
+ this->public.file_loggers->destroy_offset(this->public.file_loggers,
+ offsetof(file_logger_t, destroy));
+ this->public.sys_loggers->destroy_offset(this->public.sys_loggers,
+ offsetof(sys_logger_t, destroy));
free(this);
}
@@ -317,38 +311,151 @@ static void lookup_uid_gid(private_daemon_t *this)
}
/**
+ * Log loaded plugins
+ */
+static void print_plugins()
+{
+ char buf[512], *plugin;
+ int len = 0;
+ enumerator_t *enumerator;
+
+ enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
+ while (len < sizeof(buf) && enumerator->enumerate(enumerator, &plugin))
+ {
+ len += snprintf(&buf[len], sizeof(buf)-len, "%s ", plugin);
+ }
+ enumerator->destroy(enumerator);
+ DBG1(DBG_DMN, "loaded plugins: %s", buf);
+}
+
+/**
+ * Initialize logging
+ */
+static void initialize_loggers(private_daemon_t *this, bool use_stderr,
+ level_t levels[])
+{
+ sys_logger_t *sys_logger;
+ file_logger_t *file_logger;
+ enumerator_t *enumerator;
+ char *facility, *filename;
+ int loggers_defined = 0;
+ debug_t group;
+ level_t def;
+ bool append;
+ FILE *file;
+
+ /* setup sysloggers */
+ enumerator = lib->settings->create_section_enumerator(lib->settings,
+ "charon.syslog");
+ while (enumerator->enumerate(enumerator, &facility))
+ {
+ loggers_defined++;
+ if (streq(facility, "daemon"))
+ {
+ sys_logger = sys_logger_create(LOG_DAEMON);
+ }
+ else if (streq(facility, "auth"))
+ {
+ sys_logger = sys_logger_create(LOG_AUTHPRIV);
+ }
+ else
+ {
+ continue;
+ }
+ def = lib->settings->get_int(lib->settings,
+ "charon.syslog.%s.default", 1, facility);
+ for (group = 0; group < DBG_MAX; group++)
+ {
+ sys_logger->set_level(sys_logger, group,
+ lib->settings->get_int(lib->settings,
+ "charon.syslog.%s.%N", def,
+ facility, debug_lower_names, group));
+ }
+ this->public.sys_loggers->insert_last(this->public.sys_loggers,
+ sys_logger);
+ this->public.bus->add_listener(this->public.bus, &sys_logger->listener);
+ }
+ enumerator->destroy(enumerator);
+
+ /* and file loggers */
+ enumerator = lib->settings->create_section_enumerator(lib->settings,
+ "charon.filelog");
+ while (enumerator->enumerate(enumerator, &filename))
+ {
+ loggers_defined++;
+ if (streq(filename, "stderr"))
+ {
+ file = stderr;
+ }
+ else if (streq(filename, "stdout"))
+ {
+ file = stdout;
+ }
+ else
+ {
+ append = lib->settings->get_bool(lib->settings,
+ "charon.filelog.%s.append", TRUE, filename);
+ file = fopen(filename, append ? "a" : "w");
+ if (file == NULL)
+ {
+ DBG1(DBG_DMN, "opening file %s for logging failed: %s",
+ filename, strerror(errno));
+ continue;
+ }
+ }
+ file_logger = file_logger_create(file);
+ def = lib->settings->get_int(lib->settings,
+ "charon.filelog.%s.default", 1, filename);
+ for (group = 0; group < DBG_MAX; group++)
+ {
+ file_logger->set_level(file_logger, group,
+ lib->settings->get_int(lib->settings,
+ "charon.filelog.%s.%N", def,
+ filename, debug_lower_names, group));
+ }
+ this->public.file_loggers->insert_last(this->public.file_loggers,
+ file_logger);
+ this->public.bus->add_listener(this->public.bus, &file_logger->listener);
+
+ }
+ enumerator->destroy(enumerator);
+
+ /* setup legacy style default loggers provided via command-line */
+ if (!loggers_defined)
+ {
+ file_logger = file_logger_create(stdout);
+ sys_logger = sys_logger_create(LOG_DAEMON);
+ this->public.bus->add_listener(this->public.bus, &file_logger->listener);
+ this->public.bus->add_listener(this->public.bus, &sys_logger->listener);
+ this->public.file_loggers->insert_last(this->public.file_loggers,
+ file_logger);
+ this->public.sys_loggers->insert_last(this->public.sys_loggers,
+ sys_logger);
+ for (group = 0; group < DBG_MAX; group++)
+ {
+ sys_logger->set_level(sys_logger, group, levels[group]);
+ if (use_stderr)
+ {
+ file_logger->set_level(file_logger, group, levels[group]);
+ }
+ }
+ }
+}
+
+/**
* Initialize the daemon
*/
static bool initialize(private_daemon_t *this, bool syslog, level_t levels[])
{
- signal_t signal;
-
/* for uncritical pseudo random numbers */
srandom(time(NULL) + getpid());
/* setup bus and it's listeners first to enable log output */
this->public.bus = bus_create();
- this->public.outlog = file_logger_create(stdout);
- this->public.syslog = sys_logger_create(LOG_DAEMON);
- this->public.authlog = sys_logger_create(LOG_AUTHPRIV);
- this->public.bus->add_listener(this->public.bus, &this->public.syslog->listener);
- this->public.bus->add_listener(this->public.bus, &this->public.outlog->listener);
- this->public.bus->add_listener(this->public.bus, &this->public.authlog->listener);
- this->public.authlog->set_level(this->public.authlog, SIG_ANY, LEVEL_AUDIT);
/* set up hook to log dbg message in library via charons message bus */
dbg = dbg_bus;
- /* apply loglevels */
- for (signal = 0; signal < DBG_MAX; signal++)
- {
- this->public.syslog->set_level(this->public.syslog,
- signal, levels[signal]);
- if (!syslog)
- {
- this->public.outlog->set_level(this->public.outlog,
- signal, levels[signal]);
- }
- }
+ initialize_loggers(this, !syslog, levels);
DBG1(DBG_DMN, "starting charon (strongSwan Version %s)", VERSION);
@@ -368,6 +475,8 @@ static bool initialize(private_daemon_t *this, bool syslog, level_t levels[])
lib->plugins->load(lib->plugins, IPSEC_PLUGINDIR,
lib->settings->get_str(lib->settings, "charon.load", PLUGINS));
+ print_plugins();
+
/* create the kernel interfaces */
this->public.kernel_interface->create_interfaces(this->public.kernel_interface);
@@ -413,45 +522,13 @@ static bool initialize(private_daemon_t *this, bool syslog, level_t levels[])
*/
static void segv_handler(int signal)
{
-#ifdef HAVE_BACKTRACE
- void *array[20];
- size_t size;
- char **strings;
- size_t i;
-
- size = backtrace(array, 20);
- strings = backtrace_symbols(array, size);
-
- DBG1(DBG_JOB, "thread %u received %s. Dumping %d frames from stack:",
- pthread_self(), signal == SIGSEGV ? "SIGSEGV" : "SIGILL", size);
-
- for (i = 0; i < size; i++)
- {
-#ifdef HAVE_DLADDR
- Dl_info info;
-
- if (dladdr(array[i], &info))
- {
- void *ptr = array[i];
- if (strstr(info.dli_fname, ".so"))
- {
- ptr = (void*)(array[i] - info.dli_fbase);
- }
- DBG1(DBG_DMN, " %s [%p]", info.dli_fname, ptr);
- }
- else
- {
-#endif /* HAVE_DLADDR */
- DBG1(DBG_DMN, " %s", strings[i]);
-#ifdef HAVE_DLADDR
- }
-#endif /* HAVE_DLADDR */
- }
- free (strings);
-#else /* !HAVE_BACKTRACE */
- DBG1(DBG_DMN, "thread %u received %s",
- pthread_self(), signal == SIGSEGV ? "SIGSEGV" : "SIGILL");
-#endif /* HAVE_BACKTRACE */
+ backtrace_t *backtrace;
+
+ DBG1(DBG_DMN, "thread %u received %d", pthread_self(), signal);
+ backtrace = backtrace_create(2);
+ backtrace->log(backtrace, stderr);
+ backtrace->destroy(backtrace);
+
DBG1(DBG_DMN, "killing ourself, received critical signal");
raise(SIGKILL);
}
@@ -483,9 +560,8 @@ private_daemon_t *daemon_create(void)
this->public.eap = NULL;
this->public.sim = NULL;
this->public.bus = NULL;
- this->public.outlog = NULL;
- this->public.syslog = NULL;
- this->public.authlog = NULL;
+ this->public.file_loggers = linked_list_create();
+ this->public.sys_loggers = linked_list_create();
#ifdef ME
this->public.connect_manager = NULL;
this->public.mediation_manager = NULL;
@@ -514,6 +590,7 @@ private_daemon_t *daemon_create(void)
sigaddset(&action.sa_mask, SIGHUP);
sigaction(SIGSEGV, &action, NULL);
sigaction(SIGILL, &action, NULL);
+ sigaction(SIGBUS, &action, NULL);
action.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &action, NULL);
@@ -555,7 +632,7 @@ int main(int argc, char *argv[])
FILE *pid_file;
struct stat stb;
level_t levels[DBG_MAX];
- int signal;
+ int group;
/* logging for library during initialization, as we have no bus yet */
dbg = dbg_stderr;
@@ -572,9 +649,9 @@ int main(int argc, char *argv[])
lookup_uid_gid(private_charon);
/* use CTRL loglevel for default */
- for (signal = 0; signal < DBG_MAX; signal++)
+ for (group = 0; group < DBG_MAX; group++)
{
- levels[signal] = LEVEL_CTRL;
+ levels[group] = LEVEL_CTRL;
}
/* handle arguments */
@@ -585,16 +662,16 @@ int main(int argc, char *argv[])
{ "version", no_argument, NULL, 'v' },
{ "use-syslog", no_argument, NULL, 'l' },
/* TODO: handle "debug-all" */
- { "debug-dmn", required_argument, &signal, DBG_DMN },
- { "debug-mgr", required_argument, &signal, DBG_MGR },
- { "debug-ike", required_argument, &signal, DBG_IKE },
- { "debug-chd", required_argument, &signal, DBG_CHD },
- { "debug-job", required_argument, &signal, DBG_JOB },
- { "debug-cfg", required_argument, &signal, DBG_CFG },
- { "debug-knl", required_argument, &signal, DBG_KNL },
- { "debug-net", required_argument, &signal, DBG_NET },
- { "debug-enc", required_argument, &signal, DBG_ENC },
- { "debug-lib", required_argument, &signal, DBG_LIB },
+ { "debug-dmn", required_argument, &group, DBG_DMN },
+ { "debug-mgr", required_argument, &group, DBG_MGR },
+ { "debug-ike", required_argument, &group, DBG_IKE },
+ { "debug-chd", required_argument, &group, DBG_CHD },
+ { "debug-job", required_argument, &group, DBG_JOB },
+ { "debug-cfg", required_argument, &group, DBG_CFG },
+ { "debug-knl", required_argument, &group, DBG_KNL },
+ { "debug-net", required_argument, &group, DBG_NET },
+ { "debug-enc", required_argument, &group, DBG_ENC },
+ { "debug-lib", required_argument, &group, DBG_LIB },
{ 0,0,0,0 }
};
@@ -613,8 +690,8 @@ int main(int argc, char *argv[])
use_syslog = TRUE;
continue;
case 0:
- /* option is in signal */
- levels[signal] = atoi(optarg);
+ /* option is in group */
+ levels[group] = atoi(optarg);
continue;
default:
usage("");
@@ -642,7 +719,7 @@ int main(int argc, char *argv[])
if (pid_file)
{
fprintf(pid_file, "%d\n", getpid());
- fchown(fileno(pid_file), charon->uid, charon->gid);
+ ignore_result(fchown(fileno(pid_file), charon->uid, charon->gid));
fclose(pid_file);
}
diff --git a/src/charon/daemon.h b/src/charon/daemon.h
index 62a286f04..89e03eb93 100644
--- a/src/charon/daemon.h
+++ b/src/charon/daemon.h
@@ -15,7 +15,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: daemon.h 4406 2008-10-10 08:36:01Z martin $
+ * $Id: daemon.h 4622 2008-11-11 10:52:37Z martin $
*/
/**
@@ -217,7 +217,7 @@ struct daemon_t {
backend_manager_t *backends;
/**
- * Manager IKEv2 cfg payload attributes
+ * Manager for IKEv2 cfg payload attributes
*/
attribute_manager_t *attributes;
@@ -252,19 +252,14 @@ struct daemon_t {
bus_t *bus;
/**
- * A bus listener logging to stdout
+ * A list of installed file_logger_t's
*/
- file_logger_t *outlog;
+ linked_list_t *file_loggers;
/**
- * A bus listener logging to syslog
+ * A list of installed sys_logger_t's
*/
- sys_logger_t *syslog;
-
- /**
- * A bus listener logging most important events
- */
- sys_logger_t *authlog;
+ linked_list_t *sys_loggers;
/**
* Kernel Interface to communicate with kernel
diff --git a/src/charon/encoding/payloads/payload.c b/src/charon/encoding/payloads/payload.c
index 17986dd58..71350458f 100644
--- a/src/charon/encoding/payloads/payload.c
+++ b/src/charon/encoding/payloads/payload.c
@@ -14,7 +14,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: payload.c 3666 2008-03-26 18:40:19Z tobias $
+ * $Id: payload.c 4618 2008-11-11 09:22:00Z tobias $
*/
@@ -62,9 +62,15 @@ ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICATION, N
ENUM_NEXT(payload_type_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION,
"ID_PEER");
ENUM_NEXT(payload_type_names, HEADER, UNKNOWN_PAYLOAD, ID_PEER,
+ "HEADER",
+ "PROPOSAL_SUBSTRUCTURE",
+ "TRANSFORM_SUBSTRUCTURE",
+ "TRANSFORM_ATTRIBUTE",
+ "TRAFFIC_SELECTOR_SUBSTRUCTURE",
+ "CONFIGURATION_ATTRIBUTE",
+ "UNKNOWN_PAYLOAD");
#else
ENUM_NEXT(payload_type_names, HEADER, UNKNOWN_PAYLOAD, EXTENSIBLE_AUTHENTICATION,
-#endif /* ME */
"HEADER",
"PROPOSAL_SUBSTRUCTURE",
"TRANSFORM_SUBSTRUCTURE",
@@ -72,6 +78,7 @@ ENUM_NEXT(payload_type_names, HEADER, UNKNOWN_PAYLOAD, EXTENSIBLE_AUTHENTICATION
"TRAFFIC_SELECTOR_SUBSTRUCTURE",
"CONFIGURATION_ATTRIBUTE",
"UNKNOWN_PAYLOAD");
+#endif /* ME */
ENUM_END(payload_type_names, UNKNOWN_PAYLOAD);
/* short forms of payload names */
@@ -98,9 +105,15 @@ ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, EXTENSIBLE_AUTHENTICAT
ENUM_NEXT(payload_type_short_names, ID_PEER, ID_PEER, EXTENSIBLE_AUTHENTICATION,
"IDp");
ENUM_NEXT(payload_type_short_names, HEADER, UNKNOWN_PAYLOAD, ID_PEER,
+ "HDR",
+ "PROP",
+ "TRANS",
+ "TRANSATTR",
+ "TSSUB",
+ "CPATTR",
+ "??");
#else
ENUM_NEXT(payload_type_short_names, HEADER, UNKNOWN_PAYLOAD, EXTENSIBLE_AUTHENTICATION,
-#endif /* ME */
"HDR",
"PROP",
"TRANS",
@@ -108,6 +121,7 @@ ENUM_NEXT(payload_type_short_names, HEADER, UNKNOWN_PAYLOAD, EXTENSIBLE_AUTHENTI
"TSSUB",
"CPATTR",
"??");
+#endif /* ME */
ENUM_END(payload_type_short_names, UNKNOWN_PAYLOAD);
/*
diff --git a/src/charon/encoding/payloads/traffic_selector_substructure.c b/src/charon/encoding/payloads/traffic_selector_substructure.c
index f6042b4b6..eb5bbc626 100644
--- a/src/charon/encoding/payloads/traffic_selector_substructure.c
+++ b/src/charon/encoding/payloads/traffic_selector_substructure.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: traffic_selector_substructure.c 3589 2008-03-13 14:14:44Z martin $
+ * $Id: traffic_selector_substructure.c 4639 2008-11-12 15:09:24Z martin $
*/
#include "traffic_selector_substructure.h"
@@ -269,8 +269,8 @@ traffic_selector_substructure_t *traffic_selector_substructure_create_from_traff
this->ip_protocol_id = traffic_selector->get_protocol(traffic_selector);
this->start_port = traffic_selector->get_from_port(traffic_selector);
this->end_port = traffic_selector->get_to_port(traffic_selector);
- this->starting_address = traffic_selector->get_from_address(traffic_selector);
- this->ending_address = traffic_selector->get_to_address(traffic_selector);
+ this->starting_address = chunk_clone(traffic_selector->get_from_address(traffic_selector));
+ this->ending_address = chunk_clone(traffic_selector->get_to_address(traffic_selector));
compute_length(this);
diff --git a/src/charon/kernel/kernel_interface.c b/src/charon/kernel/kernel_interface.c
index 3c82b580e..f078f3a00 100644
--- a/src/charon/kernel/kernel_interface.c
+++ b/src/charon/kernel/kernel_interface.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: kernel_interface.c 4406 2008-10-10 08:36:01Z martin $
+ * $Id: kernel_interface.c 4655 2008-11-14 13:04:22Z martin $
*/
#include "kernel_interface.h"
@@ -85,43 +85,34 @@ static status_t get_cpi(private_kernel_interface_t *this, host_t *src, host_t *d
static status_t add_sa(private_kernel_interface_t *this, host_t *src, host_t *dst,
u_int32_t spi, protocol_id_t protocol, u_int32_t reqid,
u_int64_t expire_soft, u_int64_t expire_hard,
- u_int16_t enc_alg, u_int16_t enc_size,
- u_int16_t int_alg, u_int16_t int_size,
- prf_plus_t *prf_plus, ipsec_mode_t mode, u_int16_t ipcomp, bool encap,
- bool update)
+ u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key,
+ ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, bool encap,
+ bool inbound)
{
return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid,
- expire_soft, expire_hard, enc_alg, enc_size, int_alg, int_size,
- prf_plus, mode, ipcomp, encap, update);
+ expire_soft, expire_hard, enc_alg, enc_key, int_alg, int_key,
+ mode, ipcomp, cpi, encap, inbound);
}
/**
* Implementation of kernel_interface_t.update_sa
*/
static status_t update_sa(private_kernel_interface_t *this, u_int32_t spi,
- protocol_id_t protocol, host_t *src, host_t *dst,
- host_t *new_src, host_t *new_dst, bool encap)
+ protocol_id_t protocol, u_int16_t cpi, host_t *src, host_t *dst,
+ host_t *new_src, host_t *new_dst, bool encap, bool new_encap)
{
- return this->ipsec->update_sa(this->ipsec, spi, protocol, src, dst, new_src,
- new_dst, encap);
-}
-
-/**
- * Implementation of kernel_interface_t.query_sa
- */
-static status_t query_sa(private_kernel_interface_t *this, host_t *dst, u_int32_t spi,
- protocol_id_t protocol, u_int32_t *use_time)
-{
- return this->ipsec->query_sa(this->ipsec, dst, spi, protocol, use_time);
+ return this->ipsec->update_sa(this->ipsec, spi, protocol, cpi, src, dst,
+ new_src, new_dst, encap, new_encap);
}
/**
* Implementation of kernel_interface_t.del_sa
*/
static status_t del_sa(private_kernel_interface_t *this, host_t *dst, u_int32_t spi,
- protocol_id_t protocol)
+ protocol_id_t protocol, u_int16_t cpi)
{
- return this->ipsec->del_sa(this->ipsec, dst, spi, protocol);
+ return this->ipsec->del_sa(this->ipsec, dst, spi, protocol, cpi);
}
/**
@@ -129,12 +120,12 @@ static status_t del_sa(private_kernel_interface_t *this, host_t *dst, u_int32_t
*/
static status_t add_policy(private_kernel_interface_t *this, host_t *src, host_t *dst,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
- policy_dir_t direction, protocol_id_t protocol,
- u_int32_t reqid, bool high_prio, ipsec_mode_t mode,
- u_int16_t ipcomp)
+ policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
+ u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool routed)
{
return this->ipsec->add_policy(this->ipsec, src, dst, src_ts, dst_ts,
- direction, protocol, reqid, high_prio, mode, ipcomp);
+ direction, spi, protocol, reqid, mode, ipcomp, cpi, routed);
}
/**
@@ -152,9 +143,9 @@ static status_t query_policy(private_kernel_interface_t *this,
*/
static status_t del_policy(private_kernel_interface_t *this,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
- policy_dir_t direction)
+ policy_dir_t direction, bool unrouted)
{
- return this->ipsec->del_policy(this->ipsec, src_ts, dst_ts, direction);
+ return this->ipsec->del_policy(this->ipsec, src_ts, dst_ts, direction, unrouted);
}
/**
@@ -231,6 +222,64 @@ static status_t del_route(private_kernel_interface_t *this, chunk_t dst_net,
/**
+ * Implementation of kernel_interface_t.get_address_by_ts
+ */
+static status_t get_address_by_ts(private_kernel_interface_t *this,
+ traffic_selector_t *ts, host_t **ip)
+{
+ enumerator_t *addrs;
+ host_t *host;
+ int family;
+ bool found = FALSE;
+
+ DBG2(DBG_KNL, "getting a local address in traffic selector %R", ts);
+
+ /* if we have a family which includes localhost, we do not
+ * search for an IP, we use the default */
+ family = ts->get_type(ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6;
+
+ if (family == AF_INET)
+ {
+ host = host_create_from_string("127.0.0.1", 0);
+ }
+ else
+ {
+ host = host_create_from_string("::1", 0);
+ }
+
+ if (ts->includes(ts, host))
+ {
+ *ip = host_create_any(family);
+ host->destroy(host);
+ DBG2(DBG_KNL, "using host %H", *ip);
+ return SUCCESS;
+ }
+ host->destroy(host);
+
+ addrs = create_address_enumerator(this, TRUE, TRUE);
+ while (addrs->enumerate(addrs, (void**)&host))
+ {
+ if (ts->includes(ts, host))
+ {
+ found = TRUE;
+ *ip = host->clone(host);
+ break;
+ }
+ }
+ addrs->destroy(addrs);
+
+ if (!found)
+ {
+ DBG1(DBG_KNL, "no local address found in traffic selector %R", ts);
+ return FAILED;
+ }
+
+ DBG2(DBG_KNL, "using host %H", *ip);
+ return SUCCESS;
+}
+
+
+/**
* Implementation of kernel_interface_t.add_ipsec_interface.
*/
static void add_ipsec_interface(private_kernel_interface_t *this,
@@ -253,7 +302,7 @@ static void remove_ipsec_interface(private_kernel_interface_t *this,
}
/**
- * Implementation of kernel_interface_t.add_ipsec_interface.
+ * Implementation of kernel_interface_t.add_net_interface.
*/
static void add_net_interface(private_kernel_interface_t *this,
kernel_net_constructor_t *create)
@@ -264,7 +313,7 @@ static void add_net_interface(private_kernel_interface_t *this,
}
/**
- * Implementation of kernel_interface_t.remove_ipsec_interface.
+ * Implementation of kernel_interface_t.remove_net_interface.
*/
static void remove_net_interface(private_kernel_interface_t *this,
kernel_net_constructor_t *create)
@@ -322,13 +371,12 @@ kernel_interface_t *kernel_interface_create()
this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
this->public.get_cpi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
- this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,u_int16_t,u_int16_t,u_int16_t,prf_plus_t*,ipsec_mode_t,u_int16_t,bool,bool))add_sa;
- this->public.update_sa = (status_t(*)(kernel_interface_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_t*,host_t*,bool))update_sa;
- this->public.query_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t*))query_sa;
- this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
- this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool,ipsec_mode_t,u_int16_t))add_policy;
+ this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool))add_sa;
+ this->public.update_sa = (status_t(*)(kernel_interface_t*,u_int32_t,protocol_id_t,u_int16_t,host_t*,host_t*,host_t*,host_t*,bool,bool))update_sa;
+ this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,u_int16_t))del_sa;
+ this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t,protocol_id_t,u_int32_t,ipsec_mode_t,u_int16_t,u_int16_t,bool))add_policy;
this->public.query_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
- this->public.del_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t))del_policy;
+ this->public.del_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,bool))del_policy;
this->public.get_source_addr = (host_t*(*)(kernel_interface_t*, host_t *dest, host_t *src))get_source_addr;
this->public.get_nexthop = (host_t*(*)(kernel_interface_t*, host_t *dest))get_nexthop;
@@ -339,6 +387,8 @@ kernel_interface_t *kernel_interface_create()
this->public.add_route = (status_t(*)(kernel_interface_t*,chunk_t,u_int8_t,host_t*,host_t*,char*)) add_route;
this->public.del_route = (status_t(*)(kernel_interface_t*,chunk_t,u_int8_t,host_t*,host_t*,char*)) del_route;
+ this->public.get_address_by_ts = (status_t(*)(kernel_interface_t*,traffic_selector_t*,host_t**))get_address_by_ts;
+
this->public.add_ipsec_interface = (void(*)(kernel_interface_t*, kernel_ipsec_constructor_t))add_ipsec_interface;
this->public.remove_ipsec_interface = (void(*)(kernel_interface_t*, kernel_ipsec_constructor_t))remove_ipsec_interface;
this->public.add_net_interface = (void(*)(kernel_interface_t*, kernel_net_constructor_t))add_net_interface;
diff --git a/src/charon/kernel/kernel_interface.h b/src/charon/kernel/kernel_interface.h
index b3bf907e5..3c3b05c81 100644
--- a/src/charon/kernel/kernel_interface.h
+++ b/src/charon/kernel/kernel_interface.h
@@ -15,7 +15,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: kernel_interface.h 4386 2008-10-08 08:23:46Z martin $
+ * $Id: kernel_interface.h 4618 2008-11-11 09:22:00Z tobias $
*/
/**
@@ -56,10 +56,6 @@ struct kernel_interface_t {
/**
* Get a SPI from the kernel.
*
- * @warning get_spi() implicitly creates an SA with
- * the allocated SPI, therefore the replace flag
- * in add_sa() must be set when installing this SA.
- *
* @param src source address of SA
* @param dst destination address of SA
* @param protocol protocol for SA (ESP/AH)
@@ -101,25 +97,24 @@ struct kernel_interface_t {
* @param expire_soft lifetime in seconds before rekeying
* @param expire_hard lifetime in seconds before delete
* @param enc_alg Algorithm to use for encryption (ESP only)
- * @param enc_size key length of encryption algorithm, if dynamic
+ * @param enc_key key to use for encryption
* @param int_alg Algorithm to use for integrity protection
- * @param int_size key length of integrity algorithm, if dynamic
- * @param prf_plus PRF to derive keys from
+ * @param int_key key to use for integrity protection
* @param mode mode of the SA (tunnel, transport)
* @param ipcomp IPComp transform to use
+ * @param cpi CPI for IPComp
* @param encap enable UDP encapsulation for NAT traversal
- * @param replace Should an already installed SA be updated?
+ * @param inbound TRUE if this is an inbound SA
* @return SUCCESS if operation completed
*/
status_t (*add_sa) (kernel_interface_t *this,
host_t *src, host_t *dst, u_int32_t spi,
protocol_id_t protocol, u_int32_t reqid,
u_int64_t expire_soft, u_int64_t expire_hard,
- u_int16_t enc_alg, u_int16_t enc_size,
- u_int16_t int_alg, u_int16_t int_size,
- prf_plus_t *prf_plus, ipsec_mode_t mode,
- u_int16_t ipcomp, bool encap,
- bool update);
+ u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key,
+ ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool encap, bool inbound);
/**
* Update the hosts on an installed SA.
@@ -131,32 +126,21 @@ struct kernel_interface_t {
*
* @param spi SPI of the SA
* @param protocol protocol for this SA (ESP/AH)
+ * @param cpi CPI for IPComp, 0 if no IPComp is used
* @param src current source address
* @param dst current destination address
* @param new_src new source address
* @param new_dst new destination address
- * @param encap use UDP encapsulation
- * @return SUCCESS if operation completed
+ * @param encap current use of UDP encapsulation
+ * @param new_encap new use of UDP encapsulation
+ * @return SUCCESS if operation completed, NOT_SUPPORTED if
+ * the kernel interface can't update the SA
*/
status_t (*update_sa)(kernel_interface_t *this,
- u_int32_t spi, protocol_id_t protocol,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
host_t *src, host_t *dst,
- host_t *new_src, host_t *new_dst, bool encap);
-
- /**
- * Query the use time of an SA.
- *
- * The use time of an SA is not the time of the last usage, but
- * the time of the first usage of the SA.
- *
- * @param dst destination address for this SA
- * @param spi SPI allocated by us or remote peer
- * @param protocol protocol for this SA (ESP/AH)
- * @param use_time pointer receives the time of this SA's last use
- * @return SUCCESS if operation completed
- */
- status_t (*query_sa) (kernel_interface_t *this, host_t *dst, u_int32_t spi,
- protocol_id_t protocol, u_int32_t *use_time);
+ host_t *new_src, host_t *new_dst,
+ bool encap, bool new_encap);
/**
* Delete a previously installed SA from the SAD.
@@ -164,10 +148,11 @@ struct kernel_interface_t {
* @param dst destination address for this SA
* @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH)
+ * @param cpi CPI for IPComp or 0
* @return SUCCESS if operation completed
*/
status_t (*del_sa) (kernel_interface_t *this, host_t *dst, u_int32_t spi,
- protocol_id_t protocol);
+ protocol_id_t protocol, u_int16_t cpi);
/**
* Add a policy to the SPD.
@@ -180,20 +165,23 @@ struct kernel_interface_t {
* @param src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param spi SPI of SA
* @param protocol protocol to use to protect traffic (AH/ESP)
* @param reqid unique ID of an SA to use to enforce policy
- * @param high_prio if TRUE, uses a higher priority than any with FALSE
* @param mode mode of SA (tunnel, transport)
* @param ipcomp the IPComp transform used
+ * @param cpi CPI for IPComp
+ * @param routed TRUE, if this policy is routed in the kernel
* @return SUCCESS if operation completed
*/
status_t (*add_policy) (kernel_interface_t *this,
host_t *src, host_t *dst,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
- policy_dir_t direction, protocol_id_t protocol,
- u_int32_t reqid, bool high_prio, ipsec_mode_t mode,
- u_int16_t ipcomp);
+ policy_dir_t direction, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid,
+ ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool routed);
/**
* Query the use time of a policy.
@@ -223,12 +211,14 @@ struct kernel_interface_t {
* @param src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param unrouted TRUE, if this policy is unrouted from the kernel
* @return SUCCESS if operation completed
*/
status_t (*del_policy) (kernel_interface_t *this,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
- policy_dir_t direction);
+ policy_dir_t direction,
+ bool unrouted);
/**
* Get our outgoing source address for a destination.
@@ -335,6 +325,17 @@ struct kernel_interface_t {
*/
/**
+ * Tries to find an ip address of a local interface that is included in the
+ * supplied traffic selector.
+ *
+ * @param ts traffic selector
+ * @param ip returned ip (has to be destroyed)
+ * @return SUCCESS if address found
+ */
+ status_t (*get_address_by_ts) (kernel_interface_t *this,
+ traffic_selector_t *ts, host_t **ip);
+
+ /**
* Register an ipsec kernel interface constructor on the manager.
*
* @param create constructor to register
diff --git a/src/charon/kernel/kernel_ipsec.c b/src/charon/kernel/kernel_ipsec.c
index bae8ee125..1fef2acca 100644
--- a/src/charon/kernel/kernel_ipsec.c
+++ b/src/charon/kernel/kernel_ipsec.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: kernel_ipsec.c 4358 2008-09-25 13:56:23Z tobias $
+ * $Id: kernel_ipsec.c 4430 2008-10-14 08:46:31Z tobias $
*/
#include "kernel_ipsec.h"
@@ -24,3 +24,10 @@ ENUM(ipsec_mode_names, MODE_TRANSPORT, MODE_BEET,
"3",
"BEET",
);
+
+ENUM(policy_dir_names, POLICY_IN, POLICY_FWD,
+ "in",
+ "out",
+ "fwd"
+);
+
diff --git a/src/charon/kernel/kernel_ipsec.h b/src/charon/kernel/kernel_ipsec.h
index 67786a74f..de7068fb9 100644
--- a/src/charon/kernel/kernel_ipsec.h
+++ b/src/charon/kernel/kernel_ipsec.h
@@ -15,7 +15,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: kernel_ipsec.h 4358 2008-09-25 13:56:23Z tobias $
+ * $Id: kernel_ipsec.h 4618 2008-11-11 09:22:00Z tobias $
*/
/**
@@ -68,6 +68,11 @@ enum policy_dir_t {
};
/**
+ * enum names for policy_dir_t.
+ */
+extern enum_name_t *policy_dir_names;
+
+/**
* Interface to the ipsec subsystem of the kernel.
*
* The kernel ipsec interface handles the communication with the kernel
@@ -83,10 +88,6 @@ struct kernel_ipsec_t {
/**
* Get a SPI from the kernel.
*
- * @warning get_spi() implicitly creates an SA with
- * the allocated SPI, therefore the replace flag
- * in add_sa() must be set when installing this SA.
- *
* @param src source address of SA
* @param dst destination address of SA
* @param protocol protocol for SA (ESP/AH)
@@ -128,25 +129,24 @@ struct kernel_ipsec_t {
* @param expire_soft lifetime in seconds before rekeying
* @param expire_hard lifetime in seconds before delete
* @param enc_alg Algorithm to use for encryption (ESP only)
- * @param enc_size key length of encryption algorithm, if dynamic
+ * @param enc_key key to use for encryption
* @param int_alg Algorithm to use for integrity protection
- * @param int_size key length of integrity algorithm, if dynamic
- * @param prf_plus PRF to derive keys from
+ * @param int_key key to use for integrity protection
* @param mode mode of the SA (tunnel, transport)
* @param ipcomp IPComp transform to use
+ * @param cpi CPI for IPComp
* @param encap enable UDP encapsulation for NAT traversal
- * @param replace Should an already installed SA be updated?
+ * @param inbound TRUE if this is an inbound SA
* @return SUCCESS if operation completed
*/
status_t (*add_sa) (kernel_ipsec_t *this,
host_t *src, host_t *dst, u_int32_t spi,
protocol_id_t protocol, u_int32_t reqid,
u_int64_t expire_soft, u_int64_t expire_hard,
- u_int16_t enc_alg, u_int16_t enc_size,
- u_int16_t int_alg, u_int16_t int_size,
- prf_plus_t *prf_plus, ipsec_mode_t mode,
- u_int16_t ipcomp, bool encap,
- bool update);
+ u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key,
+ ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool encap, bool inbound);
/**
* Update the hosts on an installed SA.
@@ -158,32 +158,21 @@ struct kernel_ipsec_t {
*
* @param spi SPI of the SA
* @param protocol protocol for this SA (ESP/AH)
+ * @param cpi CPI for IPComp, 0 if no IPComp is used
* @param src current source address
* @param dst current destination address
* @param new_src new source address
* @param new_dst new destination address
- * @param encap use UDP encapsulation
- * @return SUCCESS if operation completed
+ * @param encap current use of UDP encapsulation
+ * @param new_encap new use of UDP encapsulation
+ * @return SUCCESS if operation completed, NOT_SUPPORTED if
+ * the kernel interface can't update the SA
*/
status_t (*update_sa)(kernel_ipsec_t *this,
- u_int32_t spi, protocol_id_t protocol,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
host_t *src, host_t *dst,
- host_t *new_src, host_t *new_dst, bool encap);
-
- /**
- * Query the use time of an SA.
- *
- * The use time of an SA is not the time of the last usage, but
- * the time of the first usage of the SA.
- *
- * @param dst destination address for this SA
- * @param spi SPI allocated by us or remote peer
- * @param protocol protocol for this SA (ESP/AH)
- * @param use_time pointer receives the time of this SA's last use
- * @return SUCCESS if operation completed
- */
- status_t (*query_sa) (kernel_ipsec_t *this, host_t *dst, u_int32_t spi,
- protocol_id_t protocol, u_int32_t *use_time);
+ host_t *new_src, host_t *new_dst,
+ bool encap, bool new_encap);
/**
* Delete a previusly installed SA from the SAD.
@@ -191,10 +180,11 @@ struct kernel_ipsec_t {
* @param dst destination address for this SA
* @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH)
+ * @param cpi CPI for IPComp or 0
* @return SUCCESS if operation completed
*/
status_t (*del_sa) (kernel_ipsec_t *this, host_t *dst, u_int32_t spi,
- protocol_id_t protocol);
+ protocol_id_t protocol, u_int16_t cpi);
/**
* Add a policy to the SPD.
@@ -207,20 +197,23 @@ struct kernel_ipsec_t {
* @param src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param spi SPI of SA
* @param protocol protocol to use to protect traffic (AH/ESP)
* @param reqid unique ID of an SA to use to enforce policy
- * @param high_prio if TRUE, uses a higher priority than any with FALSE
* @param mode mode of SA (tunnel, transport)
* @param ipcomp the IPComp transform used
+ * @param cpi CPI for IPComp
+ * @param routed TRUE, if this policy is routed in the kernel
* @return SUCCESS if operation completed
*/
status_t (*add_policy) (kernel_ipsec_t *this,
host_t *src, host_t *dst,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
- policy_dir_t direction, protocol_id_t protocol,
- u_int32_t reqid, bool high_prio, ipsec_mode_t mode,
- u_int16_t ipcomp);
+ policy_dir_t direction, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid,
+ ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool routed);
/**
* Query the use time of a policy.
@@ -250,12 +243,14 @@ struct kernel_ipsec_t {
* @param src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param unrouted TRUE, if this policy is unrouted from the kernel
* @return SUCCESS if operation completed
*/
status_t (*del_policy) (kernel_ipsec_t *this,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
- policy_dir_t direction);
+ policy_dir_t direction,
+ bool unrouted);
/**
* Destroy the implementation.
diff --git a/src/charon/network/sender.c b/src/charon/network/sender.c
index 60a08d0c3..3295ec2df 100644
--- a/src/charon/network/sender.c
+++ b/src/charon/network/sender.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: sender.c 3742 2008-04-03 09:19:12Z tobias $
+ * $Id: sender.c 4582 2008-11-05 12:24:36Z martin $
*/
#include <stdlib.h>
@@ -24,6 +24,7 @@
#include <daemon.h>
#include <network/socket.h>
#include <processing/jobs/callback_job.h>
+#include <utils/mutex.h>
typedef struct private_sender_t private_sender_t;
@@ -50,17 +51,17 @@ struct private_sender_t {
/**
* mutex to synchronize access to list
*/
- pthread_mutex_t mutex;
+ mutex_t *mutex;
/**
* condvar to signal for packets added to list
*/
- pthread_cond_t gotone;
+ condvar_t *got;
/**
* condvar to signal for packets sent
*/
- pthread_cond_t sentone;
+ condvar_t *sent;
};
/**
@@ -74,10 +75,10 @@ static void send_(private_sender_t *this, packet_t *packet)
dst = packet->get_destination(packet);
DBG1(DBG_NET, "sending packet: from %#H to %#H", src, dst);
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
this->list->insert_last(this->list, packet);
- pthread_cond_signal(&this->gotone);
- pthread_mutex_unlock(&this->mutex);
+ this->got->signal(this->got);
+ this->mutex->unlock(this->mutex);
}
/**
@@ -88,21 +89,21 @@ static job_requeue_t send_packets(private_sender_t * this)
packet_t *packet;
int oldstate;
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
while (this->list->get_count(this->list) == 0)
{
/* add cleanup handler, wait for packet, remove cleanup handler */
- pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&this->mutex);
+ pthread_cleanup_push((void(*)(void*))this->mutex->unlock, this->mutex);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
- pthread_cond_wait(&this->gotone, &this->mutex);
+ this->got->wait(this->got, this->mutex);
pthread_setcancelstate(oldstate, NULL);
pthread_cleanup_pop(0);
}
this->list->remove_first(this->list, (void**)&packet);
- pthread_cond_signal(&this->sentone);
- pthread_mutex_unlock(&this->mutex);
+ this->sent->signal(this->sent);
+ this->mutex->unlock(this->mutex);
charon->socket->send(charon->socket, packet);
packet->destroy(packet);
@@ -115,15 +116,17 @@ static job_requeue_t send_packets(private_sender_t * this)
static void destroy(private_sender_t *this)
{
/* send all packets in the queue */
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
while (this->list->get_count(this->list))
{
- pthread_cond_wait(&this->sentone, &this->mutex);
+ this->sent->wait(this->sent, this->mutex);
}
- pthread_mutex_unlock(&this->mutex);
- pthread_mutex_destroy(&this->mutex);
+ this->mutex->unlock(this->mutex);
this->job->cancel(this->job);
this->list->destroy(this->list);
+ this->got->destroy(this->got);
+ this->sent->destroy(this->sent);
+ this->mutex->destroy(this->mutex);
free(this);
}
@@ -133,19 +136,19 @@ static void destroy(private_sender_t *this)
sender_t * sender_create()
{
private_sender_t *this = malloc_thing(private_sender_t);
-
+
this->public.send = (void(*)(sender_t*,packet_t*))send_;
this->public.destroy = (void(*)(sender_t*)) destroy;
-
+
this->list = linked_list_create();
- pthread_mutex_init(&this->mutex, NULL);
- pthread_cond_init(&this->gotone, NULL);
- pthread_cond_init(&this->sentone, NULL);
-
+ this->mutex = mutex_create(MUTEX_DEFAULT);
+ this->got = condvar_create(CONDVAR_DEFAULT);
+ this->sent = condvar_create(CONDVAR_DEFAULT);
+
this->job = callback_job_create((callback_job_cb_t)send_packets,
this, NULL, NULL);
charon->processor->queue_job(charon->processor, (job_t*)this->job);
-
+
return &this->public;
}
diff --git a/src/charon/network/socket-raw.c b/src/charon/network/socket-raw.c
index 5d1623ffd..40218f67d 100644
--- a/src/charon/network/socket-raw.c
+++ b/src/charon/network/socket-raw.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
- * 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: socket-raw.c 3870 2008-04-24 13:49:20Z martin $
+ * $Id: socket-raw.c 4646 2008-11-13 07:15:45Z martin $
*/
/* for struct in6_pktinfo */
@@ -33,7 +33,7 @@
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/udp.h>
-#include <linux/ipsec.h>
+#include <linux/types.h>
#include <linux/filter.h>
#include <net/if.h>
@@ -53,11 +53,6 @@
#define IKE_VERSION_OFFSET 17
#define IKE_LENGTH_OFFSET 24
-/* from linux/in.h */
-#ifndef IP_IPSEC_POLICY
-#define IP_IPSEC_POLICY 16
-#endif /*IP_IPSEC_POLICY*/
-
/* from linux/udp.h */
#ifndef UDP_ENCAP
#define UDP_ENCAP 100
@@ -72,11 +67,6 @@
#define IPV6_2292PKTINFO 2
#endif /*IPV6_2292PKTINFO*/
-/* missing on uclibc */
-#ifndef IPV6_IPSEC_POLICY
-#define IPV6_IPSEC_POLICY 34
-#endif /*IPV6_IPSEC_POLICY*/
-
typedef struct private_socket_t private_socket_t;
/**
@@ -440,8 +430,7 @@ static int open_send_socket(private_socket_t *this, int family, u_int16_t port)
int on = TRUE;
int type = UDP_ENCAP_ESPINUDP;
struct sockaddr_storage addr;
- u_int sol, ipsec_policy;
- struct sadb_x_policy policy;
+ u_int sol;
int skt;
memset(&addr, 0, sizeof(addr));
@@ -455,7 +444,6 @@ static int open_send_socket(private_socket_t *this, int family, u_int16_t port)
sin->sin_addr.s_addr = INADDR_ANY;
sin->sin_port = htons(port);
sol = SOL_IP;
- ipsec_policy = IP_IPSEC_POLICY;
break;
}
case AF_INET6:
@@ -465,7 +453,6 @@ static int open_send_socket(private_socket_t *this, int family, u_int16_t port)
memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any));
sin6->sin6_port = htons(port);
sol = SOL_IPV6;
- ipsec_policy = IPV6_IPSEC_POLICY;
break;
}
default:
@@ -487,32 +474,6 @@ static int open_send_socket(private_socket_t *this, int family, u_int16_t port)
return 0;
}
- /* bypass outgoung IKE traffic on send socket */
- memset(&policy, 0, sizeof(policy));
- policy.sadb_x_policy_len = sizeof(policy) / sizeof(u_int64_t);
- policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
- policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS;
- policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
-
- if (setsockopt(skt, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
- {
- DBG1(DBG_NET, "unable to set IPSEC_POLICY on send socket: %s",
- strerror(errno));
- close(skt);
- return 0;
- }
-
- /* We don't receive packets on the send socket, but we need a INBOUND policy.
- * Otherwise, UDP decapsulation does not work!!! */
- policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
- if (setsockopt(skt, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
- {
- DBG1(DBG_NET, "unable to set IPSEC_POLICY on send socket: %s",
- strerror(errno));
- close(skt);
- return 0;
- }
-
/* bind the send socket */
if (bind(skt, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
@@ -542,8 +503,7 @@ static int open_recv_socket(private_socket_t *this, int family)
{
int skt;
int on = TRUE;
- u_int proto_offset, ip_len, sol, ipsec_policy, udp_header, ike_header;
- struct sadb_x_policy policy;
+ u_int proto_offset, ip_len, sol, udp_header, ike_header;
/* precalculate constants depending on address family */
switch (family)
@@ -552,13 +512,11 @@ static int open_recv_socket(private_socket_t *this, int family)
proto_offset = IP_PROTO_OFFSET;
ip_len = IP_LEN;
sol = SOL_IP;
- ipsec_policy = IP_IPSEC_POLICY;
break;
case AF_INET6:
proto_offset = IP6_PROTO_OFFSET;
ip_len = 0; /* IPv6 raw sockets contain no IP header */
sol = SOL_IPV6;
- ipsec_policy = IPV6_IPSEC_POLICY;
break;
default:
return 0;
@@ -633,22 +591,67 @@ static int open_recv_socket(private_socket_t *this, int family)
return 0;
}
- /* bypass incomining IKE traffic on this socket */
- memset(&policy, 0, sizeof(policy));
- policy.sadb_x_policy_len = sizeof(policy) / sizeof(u_int64_t);
- policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
- policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS;
- policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
+ return skt;
+}
+
+/**
+ * enumerator for underlying sockets
+ */
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** sockets we enumerate */
+ private_socket_t *socket;
+ /** counter */
+ int index;
+} socket_enumerator_t;
+
+/**
+ * enumerate function for socket_enumerator_t
+ */
+static bool enumerate(socket_enumerator_t *this, int *fd, int *family, int *port)
+{
+ static const struct {
+ int fd_offset;
+ int family;
+ int port;
+ } sockets[] = {
+ { offsetof(private_socket_t, recv4), AF_INET, IKEV2_UDP_PORT },
+ { offsetof(private_socket_t, recv6), AF_INET6, IKEV2_UDP_PORT },
+ { offsetof(private_socket_t, send4), AF_INET, IKEV2_UDP_PORT },
+ { offsetof(private_socket_t, send6), AF_INET6, IKEV2_UDP_PORT },
+ { offsetof(private_socket_t, send4_natt), AF_INET, IKEV2_NATT_PORT },
+ { offsetof(private_socket_t, send6_natt), AF_INET6, IKEV2_NATT_PORT }
+ };
- if (setsockopt(skt, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
+ while(++this->index < countof(sockets))
{
- DBG1(DBG_NET, "unable to set IPSEC_POLICY on raw socket: %s",
- strerror(errno));
- close(skt);
- return 0;
+ int sock = *(int*)((char*)this->socket + sockets[this->index].fd_offset);
+ if (!sock)
+ {
+ continue;
+ }
+ *fd = sock;
+ *family = sockets[this->index].family;
+ *port = sockets[this->index].port;
+ return TRUE;
}
-
- return skt;
+ return FALSE;
+}
+
+/**
+ * implementation of socket_t.create_enumerator
+ */
+static enumerator_t *create_enumerator(private_socket_t *this)
+{
+ socket_enumerator_t *enumerator;
+
+ enumerator = malloc_thing(socket_enumerator_t);
+ enumerator->index = -1;
+ enumerator->socket = this;
+ enumerator->public.enumerate = (void*)enumerate;
+ enumerator->public.destroy = (void*)free;
+ return &enumerator->public;
}
/**
@@ -688,12 +691,12 @@ static void destroy(private_socket_t *this)
*/
socket_t *socket_create()
{
- int key;
private_socket_t *this = malloc_thing(private_socket_t);
-
+
/* public functions */
this->public.send = (status_t(*)(socket_t*, packet_t*))sender;
this->public.receive = (status_t(*)(socket_t*, packet_t**))receiver;
+ this->public.create_enumerator = (enumerator_t*(*)(socket_t*))create_enumerator;
this->public.destroy = (void(*)(socket_t*)) destroy;
this->recv4 = 0;
@@ -703,15 +706,6 @@ socket_t *socket_create()
this->send4_natt = 0;
this->send6_natt = 0;
- /* we open a AF_KEY socket to autoload the af_key module. Otherwise
- * setsockopt(IPSEC_POLICY) won't work. */
- key = socket(AF_KEY, SOCK_RAW, PF_KEY_V2);
- if (key == 0)
- {
- charon->kill(charon, "could not open AF_KEY socket");
- }
- close(key);
-
this->recv4 = open_recv_socket(this, AF_INET);
if (this->recv4 == 0)
{
diff --git a/src/charon/network/socket.c b/src/charon/network/socket.c
index 60ea5f7c8..6be59ef62 100644
--- a/src/charon/network/socket.c
+++ b/src/charon/network/socket.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
+ * Copyright (C) 2006-2008 Tobias Brunner
+ * Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -14,7 +15,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: socket.c 3870 2008-04-24 13:49:20Z martin $
+ * $Id: socket.c 4646 2008-11-13 07:15:45Z martin $
*/
/* for struct in6_pktinfo */
@@ -33,7 +34,7 @@
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/udp.h>
-#include <linux/ipsec.h>
+#include <linux/types.h>
#include <linux/filter.h>
#include <net/if.h>
@@ -44,11 +45,6 @@
/* length of non-esp marker */
#define MARKER_LEN sizeof(u_int32_t)
-/* from linux/in.h */
-#ifndef IP_IPSEC_POLICY
-#define IP_IPSEC_POLICY 16
-#endif /*IP_IPSEC_POLICY*/
-
/* from linux/udp.h */
#ifndef UDP_ENCAP
#define UDP_ENCAP 100
@@ -405,8 +401,7 @@ static int open_socket(private_socket_t *this, int family, u_int16_t port)
int on = TRUE;
int type = UDP_ENCAP_ESPINUDP;
struct sockaddr_storage addr;
- u_int sol, ipsec_policy, pktinfo;
- struct sadb_x_policy policy;
+ u_int sol, pktinfo;
int skt;
memset(&addr, 0, sizeof(addr));
@@ -420,7 +415,6 @@ static int open_socket(private_socket_t *this, int family, u_int16_t port)
sin->sin_addr.s_addr = INADDR_ANY;
sin->sin_port = htons(port);
sol = SOL_IP;
- ipsec_policy = IP_IPSEC_POLICY;
pktinfo = IP_PKTINFO;
break;
}
@@ -431,7 +425,6 @@ static int open_socket(private_socket_t *this, int family, u_int16_t port)
memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any));
sin6->sin6_port = htons(port);
sol = SOL_IPV6;
- ipsec_policy = IPV6_IPSEC_POLICY;
pktinfo = IPV6_2292PKTINFO;
break;
}
@@ -452,29 +445,6 @@ static int open_socket(private_socket_t *this, int family, u_int16_t port)
return 0;
}
- /* bypass IKE traffic on socket */
- memset(&policy, 0, sizeof(policy));
- policy.sadb_x_policy_len = sizeof(policy) / sizeof(u_int64_t);
- policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
- policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS;
-
- policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
- if (setsockopt(skt, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
- {
- DBG1(DBG_NET, "unable to set IPSEC_POLICY on socket: %s",
- strerror(errno));
- close(skt);
- return 0;
- }
- policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
- if (setsockopt(skt, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
- {
- DBG1(DBG_NET, "unable to set IPSEC_POLICY on socket: %s",
- strerror(errno));
- close(skt);
- return 0;
- }
-
/* bind the send socket */
if (bind(skt, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
@@ -501,6 +471,64 @@ static int open_socket(private_socket_t *this, int family, u_int16_t port)
}
/**
+ * enumerator for underlying sockets
+ */
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** sockets we enumerate */
+ private_socket_t *socket;
+ /** counter */
+ int index;
+} socket_enumerator_t;
+
+/**
+ * enumerate function for socket_enumerator_t
+ */
+static bool enumerate(socket_enumerator_t *this, int *fd, int *family, int *port)
+{
+ static const struct {
+ int fd_offset;
+ int family;
+ int port;
+ } sockets[] = {
+ { offsetof(private_socket_t, ipv4), AF_INET, IKEV2_UDP_PORT },
+ { offsetof(private_socket_t, ipv6), AF_INET6, IKEV2_UDP_PORT },
+ { offsetof(private_socket_t, ipv4_natt), AF_INET, IKEV2_NATT_PORT },
+ { offsetof(private_socket_t, ipv6_natt), AF_INET6, IKEV2_NATT_PORT }
+ };
+
+ while(++this->index < countof(sockets))
+ {
+ int sock = *(int*)((char*)this->socket + sockets[this->index].fd_offset);
+ if (!sock)
+ {
+ continue;
+ }
+ *fd = sock;
+ *family = sockets[this->index].family;
+ *port = sockets[this->index].port;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * implementation of socket_t.create_enumerator
+ */
+static enumerator_t *create_enumerator(private_socket_t *this)
+{
+ socket_enumerator_t *enumerator;
+
+ enumerator = malloc_thing(socket_enumerator_t);
+ enumerator->index = -1;
+ enumerator->socket = this;
+ enumerator->public.enumerate = (void*)enumerate;
+ enumerator->public.destroy = (void*)free;
+ return &enumerator->public;
+}
+
+/**
* implementation of socket_t.destroy
*/
static void destroy(private_socket_t *this)
@@ -529,12 +557,12 @@ static void destroy(private_socket_t *this)
*/
socket_t *socket_create()
{
- int key;
private_socket_t *this = malloc_thing(private_socket_t);
/* public functions */
this->public.send = (status_t(*)(socket_t*, packet_t*))sender;
this->public.receive = (status_t(*)(socket_t*, packet_t**))receiver;
+ this->public.create_enumerator = (enumerator_t*(*)(socket_t*))create_enumerator;
this->public.destroy = (void(*)(socket_t*)) destroy;
this->ipv4 = 0;
@@ -542,15 +570,6 @@ socket_t *socket_create()
this->ipv4_natt = 0;
this->ipv6_natt = 0;
- /* we open a AF_KEY socket to autoload the af_key module. Otherwise
- * setsockopt(IPSEC_POLICY) won't work. */
- key = socket(AF_KEY, SOCK_RAW, PF_KEY_V2);
- if (key == 0)
- {
- charon->kill(charon, "could not open AF_KEY socket");
- }
- close(key);
-
this->ipv4 = open_socket(this, AF_INET, IKEV2_UDP_PORT);
if (this->ipv4 == 0)
{
diff --git a/src/charon/network/socket.h b/src/charon/network/socket.h
index b76a9b0c3..4e967f721 100644
--- a/src/charon/network/socket.h
+++ b/src/charon/network/socket.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
- * 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: socket.h 4355 2008-09-25 07:56:58Z tobias $
+ * $Id: socket.h 4647 2008-11-13 07:48:27Z martin $
*/
/**
@@ -30,15 +30,13 @@ typedef struct socket_t socket_t;
#include <library.h>
#include <network/packet.h>
#include <utils/host.h>
-#include <utils/linked_list.h>
+#include <utils/enumerator.h>
/**
* Maximum size of a packet.
*
- * 3000 Bytes should be sufficient, see IKEv2 RFC. However, we currently
- * do not support HASH_AND_URL certificates, so we require to transmit
- * the full certificates. To run our multi-CA test with 2 intermediate CAs,
- * 5000 bytes is sufficient.
+ * 3000 Bytes should be sufficient, see IKEv2 RFC. However, to run our
+ * multi-CA test with 2 intermediate CAs, we increase that to 5000 bytes.
*/
#define MAX_PACKET 5000
@@ -73,9 +71,8 @@ struct socket_t {
/**
* Send a packet.
*
- * Sends a packet to the net using destination from the packet.
- * Packet is sent using default routing mechanisms, thus the
- * source address in packet is ignored.
+ * Sends a packet to the net using source and destination addresses of
+ * the packet.
*
* @param packet packet_t to send
* @return
@@ -85,6 +82,13 @@ struct socket_t {
status_t (*send) (socket_t *this, packet_t *packet);
/**
+ * Enumerate all underlying socket file descriptors.
+ *
+ * @return enumerator over (int fd, int family, int port)
+ */
+ enumerator_t *(*create_enumerator) (socket_t *this);
+
+ /**
* Destroy socket.
*/
void (*destroy) (socket_t *this);
diff --git a/src/charon/plugins/eap_aka/eap_aka.c b/src/charon/plugins/eap_aka/eap_aka.c
index 4c0f76b7f..bb3825d3d 100644
--- a/src/charon/plugins/eap_aka/eap_aka.c
+++ b/src/charon/plugins/eap_aka/eap_aka.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: eap_aka.c 4276 2008-08-22 10:44:51Z martin $
+ * $Id: eap_aka.c 4628 2008-11-11 15:19:13Z martin $
*/
@@ -35,6 +35,7 @@
* - server_initiate_challenge() - Initiation of AKA-Challenge
*/
+#include <limits.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
diff --git a/src/charon/plugins/kernel_klips/Makefile.am b/src/charon/plugins/kernel_klips/Makefile.am
new file mode 100644
index 000000000..dc0234775
--- /dev/null
+++ b/src/charon/plugins/kernel_klips/Makefile.am
@@ -0,0 +1,10 @@
+
+INCLUDES = -I${linuxdir} -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
+
+AM_CFLAGS = -rdynamic
+
+plugin_LTLIBRARIES = libstrongswan-kernel-klips.la
+
+libstrongswan_kernel_klips_la_SOURCES = kernel_klips_plugin.h kernel_klips_plugin.c \
+ kernel_klips_ipsec.h kernel_klips_ipsec.c pfkeyv2.h
+libstrongswan_kernel_klips_la_LDFLAGS = -module
diff --git a/src/charon/plugins/kernel_klips/Makefile.in b/src/charon/plugins/kernel_klips/Makefile.in
new file mode 100644
index 000000000..702b38394
--- /dev/null
+++ b/src/charon/plugins/kernel_klips/Makefile.in
@@ -0,0 +1,501 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/charon/plugins/kernel_klips
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(plugindir)"
+pluginLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+libstrongswan_kernel_klips_la_LIBADD =
+am_libstrongswan_kernel_klips_la_OBJECTS = kernel_klips_plugin.lo \
+ kernel_klips_ipsec.lo
+libstrongswan_kernel_klips_la_OBJECTS = \
+ $(am_libstrongswan_kernel_klips_la_OBJECTS)
+libstrongswan_kernel_klips_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_kernel_klips_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_kernel_klips_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_kernel_klips_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@
+IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LINUX_HEADERS = @LINUX_HEADERS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+confdir = @confdir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libstrongswan_plugins = @libstrongswan_plugins@
+linuxdir = @linuxdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+resolv_conf = @resolv_conf@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+simreader = @simreader@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+INCLUDES = -I${linuxdir} -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
+AM_CFLAGS = -rdynamic
+plugin_LTLIBRARIES = libstrongswan-kernel-klips.la
+libstrongswan_kernel_klips_la_SOURCES = kernel_klips_plugin.h kernel_klips_plugin.c \
+ kernel_klips_ipsec.h kernel_klips_ipsec.c pfkeyv2.h
+
+libstrongswan_kernel_klips_la_LDFLAGS = -module
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/kernel_klips/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/charon/plugins/kernel_klips/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-kernel-klips.la: $(libstrongswan_kernel_klips_la_OBJECTS) $(libstrongswan_kernel_klips_la_DEPENDENCIES)
+ $(libstrongswan_kernel_klips_la_LINK) -rpath $(plugindir) $(libstrongswan_kernel_klips_la_OBJECTS) $(libstrongswan_kernel_klips_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_klips_ipsec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_klips_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+
+# 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/charon/plugins/kernel_klips/kernel_klips_ipsec.c b/src/charon/plugins/kernel_klips/kernel_klips_ipsec.c
new file mode 100644
index 000000000..91bef0a54
--- /dev/null
+++ b/src/charon/plugins/kernel_klips/kernel_klips_ipsec.c
@@ -0,0 +1,2659 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * 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: kernel_klips_ipsec.c 4631 2008-11-11 18:35:10Z martin $
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <stdint.h>
+#include "pfkeyv2.h"
+#include <linux/udp.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+#include "kernel_klips_ipsec.h"
+
+#include <daemon.h>
+#include <utils/mutex.h>
+#include <processing/jobs/callback_job.h>
+#include <processing/jobs/acquire_job.h>
+#include <processing/jobs/rekey_child_sa_job.h>
+#include <processing/jobs/delete_child_sa_job.h>
+#include <processing/jobs/update_sa_job.h>
+
+/** default timeout for generated SPIs (in seconds) */
+#define SPI_TIMEOUT 30
+
+/** buffer size for PF_KEY messages */
+#define PFKEY_BUFFER_SIZE 2048
+
+/** PF_KEY messages are 64 bit aligned */
+#define PFKEY_ALIGNMENT 8
+/** aligns len to 64 bits */
+#define PFKEY_ALIGN(len) (((len) + PFKEY_ALIGNMENT - 1) & ~(PFKEY_ALIGNMENT - 1))
+/** calculates the properly padded length in 64 bit chunks */
+#define PFKEY_LEN(len) ((PFKEY_ALIGN(len) / PFKEY_ALIGNMENT))
+/** calculates user mode length i.e. in bytes */
+#define PFKEY_USER_LEN(len) ((len) * PFKEY_ALIGNMENT)
+
+/** given a PF_KEY message header and an extension this updates the length in the header */
+#define PFKEY_EXT_ADD(msg, ext) ((msg)->sadb_msg_len += ((struct sadb_ext*)ext)->sadb_ext_len)
+/** given a PF_KEY message header this returns a pointer to the next extension */
+#define PFKEY_EXT_ADD_NEXT(msg) ((struct sadb_ext*)(((char*)(msg)) + PFKEY_USER_LEN((msg)->sadb_msg_len)))
+/** copy an extension and append it to a PF_KEY message */
+#define PFKEY_EXT_COPY(msg, ext) (PFKEY_EXT_ADD(msg, memcpy(PFKEY_EXT_ADD_NEXT(msg), ext, PFKEY_USER_LEN(((struct sadb_ext*)ext)->sadb_ext_len))))
+/** given a PF_KEY extension this returns a pointer to the next extension */
+#define PFKEY_EXT_NEXT(ext) ((struct sadb_ext*)(((char*)(ext)) + PFKEY_USER_LEN(((struct sadb_ext*)ext)->sadb_ext_len)))
+/** given a PF_KEY extension this returns a pointer to the next extension also updates len (len in 64 bit words) */
+#define PFKEY_EXT_NEXT_LEN(ext,len) ((len) -= (ext)->sadb_ext_len, PFKEY_EXT_NEXT(ext))
+/** true if ext has a valid length and len is large enough to contain ext (assuming len in 64 bit words) */
+#define PFKEY_EXT_OK(ext,len) ((len) >= PFKEY_LEN(sizeof(struct sadb_ext)) && \
+ (ext)->sadb_ext_len >= PFKEY_LEN(sizeof(struct sadb_ext)) && \
+ (ext)->sadb_ext_len <= (len))
+
+/** special SPI values used for policies in KLIPS */
+#define SPI_PASS 256
+#define SPI_DROP 257
+#define SPI_REJECT 258
+#define SPI_HOLD 259
+#define SPI_TRAP 260
+#define SPI_TRAPSUBNET 261
+
+/** the prefix of the name of KLIPS ipsec devices */
+#define IPSEC_DEV_PREFIX "ipsec"
+/** this is the default number of ipsec devices */
+#define DEFAULT_IPSEC_DEV_COUNT 4
+/** TRUE if the given name matches an ipsec device */
+#define IS_IPSEC_DEV(name) (strneq((name), IPSEC_DEV_PREFIX, sizeof(IPSEC_DEV_PREFIX) - 1))
+
+/** the following stuff is from ipsec_tunnel.h */
+struct ipsectunnelconf
+{
+ __u32 cf_cmd;
+ union
+ {
+ char cfu_name[12];
+ } cf_u;
+#define cf_name cf_u.cfu_name
+};
+
+#define IPSEC_SET_DEV (SIOCDEVPRIVATE)
+#define IPSEC_DEL_DEV (SIOCDEVPRIVATE + 1)
+#define IPSEC_CLR_DEV (SIOCDEVPRIVATE + 2)
+
+typedef struct private_kernel_klips_ipsec_t private_kernel_klips_ipsec_t;
+
+/**
+ * Private variables and functions of kernel_klips class.
+ */
+struct private_kernel_klips_ipsec_t
+{
+ /**
+ * Public part of the kernel_klips_t object.
+ */
+ kernel_klips_ipsec_t public;
+
+ /**
+ * mutex to lock access to various lists
+ */
+ mutex_t *mutex;
+
+ /**
+ * List of installed policies (policy_entry_t)
+ */
+ linked_list_t *policies;
+
+ /**
+ * List of allocated SPIs without installed SA (sa_entry_t)
+ */
+ linked_list_t *allocated_spis;
+
+ /**
+ * List of installed SAs (sa_entry_t)
+ */
+ linked_list_t *installed_sas;
+
+ /**
+ * whether to install routes along policies
+ */
+ bool install_routes;
+
+ /**
+ * List of ipsec devices (ipsec_dev_t)
+ */
+ linked_list_t *ipsec_devices;
+
+ /**
+ * job receiving PF_KEY events
+ */
+ callback_job_t *job;
+
+ /**
+ * mutex to lock access to the PF_KEY socket
+ */
+ mutex_t *mutex_pfkey;
+
+ /**
+ * PF_KEY socket to communicate with the kernel
+ */
+ int socket;
+
+ /**
+ * PF_KEY socket to receive acquire and expire events
+ */
+ int socket_events;
+
+ /**
+ * sequence number for messages sent to the kernel
+ */
+ int seq;
+
+};
+
+
+typedef struct ipsec_dev_t ipsec_dev_t;
+
+/**
+ * ipsec device
+ */
+struct ipsec_dev_t {
+ /** name of the virtual ipsec interface */
+ char name[IFNAMSIZ];
+
+ /** name of the physical interface */
+ char phys_name[IFNAMSIZ];
+
+ /** by how many CHILD_SA's this ipsec device is used */
+ u_int refcount;
+};
+
+/**
+ * compare the given name with the virtual device name
+ */
+static inline bool ipsec_dev_match_byname(ipsec_dev_t *current, char *name)
+{
+ return name && streq(current->name, name);
+}
+
+/**
+ * compare the given name with the physical device name
+ */
+static inline bool ipsec_dev_match_byphys(ipsec_dev_t *current, char *name)
+{
+ return name && streq(current->phys_name, name);
+}
+
+/**
+ * matches free ipsec devices
+ */
+static inline bool ipsec_dev_match_free(ipsec_dev_t *current)
+{
+ return current->refcount == 0;
+}
+
+/**
+ * tries to find an ipsec_dev_t object by name
+ */
+static status_t find_ipsec_dev(private_kernel_klips_ipsec_t *this, char *name,
+ ipsec_dev_t **dev)
+{
+ linked_list_match_t match = (linked_list_match_t)(IS_IPSEC_DEV(name) ?
+ ipsec_dev_match_byname : ipsec_dev_match_byphys);
+ return this->ipsec_devices->find_first(this->ipsec_devices, match,
+ (void**)dev, name);
+}
+
+/**
+ * attach an ipsec device to a physical interface
+ */
+static status_t attach_ipsec_dev(char* name, char *phys_name)
+{
+ int sock;
+ struct ifreq req;
+ struct ipsectunnelconf *itc = (struct ipsectunnelconf*)&req.ifr_data;
+ short phys_flags;
+ int mtu;
+
+ DBG2(DBG_KNL, "attaching virtual interface %s to %s", name, phys_name);
+
+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) <= 0)
+ {
+ return FAILED;
+ }
+
+ strncpy(req.ifr_name, phys_name, IFNAMSIZ);
+ if (ioctl(sock, SIOCGIFFLAGS, &req) < 0)
+ {
+ close(sock);
+ return FAILED;
+ }
+ phys_flags = req.ifr_flags;
+
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ if (ioctl(sock, SIOCGIFFLAGS, &req) < 0)
+ {
+ close(sock);
+ return FAILED;
+ }
+
+ if (req.ifr_flags & IFF_UP)
+ {
+ /* if it's already up, it is already attached, detach it first */
+ ioctl(sock, IPSEC_DEL_DEV, &req);
+ }
+
+ /* attach it */
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ strncpy(itc->cf_name, phys_name, sizeof(itc->cf_name));
+ ioctl(sock, IPSEC_SET_DEV, &req);
+
+ /* copy address from physical to virtual */
+ strncpy(req.ifr_name, phys_name, IFNAMSIZ);
+ if (ioctl(sock, SIOCGIFADDR, &req) == 0)
+ {
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ ioctl(sock, SIOCSIFADDR, &req);
+ }
+
+ /* copy net mask from physical to virtual */
+ strncpy(req.ifr_name, phys_name, IFNAMSIZ);
+ if (ioctl(sock, SIOCGIFNETMASK, &req) == 0)
+ {
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ ioctl(sock, SIOCSIFNETMASK, &req);
+ }
+
+ /* copy other flags and addresses */
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ if (ioctl(sock, SIOCGIFFLAGS, &req) == 0)
+ {
+ if (phys_flags & IFF_POINTOPOINT)
+ {
+ req.ifr_flags |= IFF_POINTOPOINT;
+ req.ifr_flags &= ~IFF_BROADCAST;
+ ioctl(sock, SIOCSIFFLAGS, &req);
+
+ strncpy(req.ifr_name, phys_name, IFNAMSIZ);
+ if (ioctl(sock, SIOCGIFDSTADDR, &req) == 0)
+ {
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ ioctl(sock, SIOCSIFDSTADDR, &req);
+ }
+ }
+ else if (phys_flags & IFF_BROADCAST)
+ {
+ req.ifr_flags &= ~IFF_POINTOPOINT;
+ req.ifr_flags |= IFF_BROADCAST;
+ ioctl(sock, SIOCSIFFLAGS, &req);
+
+ strncpy(req.ifr_name, phys_name, IFNAMSIZ);
+ if (ioctl(sock, SIOCGIFBRDADDR, &req)==0)
+ {
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ ioctl(sock, SIOCSIFBRDADDR, &req);
+ }
+ }
+ else
+ {
+ req.ifr_flags &= ~IFF_POINTOPOINT;
+ req.ifr_flags &= ~IFF_BROADCAST;
+ ioctl(sock, SIOCSIFFLAGS, &req);
+ }
+ }
+
+ mtu = lib->settings->get_int(lib->settings,
+ "charon.plugins.kernel_klips.ipsec_dev_mtu", 0);
+ if (mtu <= 0)
+ {
+ /* guess MTU as physical MTU - ESP overhead [- NAT-T overhead]
+ * ESP overhead : 73 bytes
+ * NAT-T overhead : 8 bytes ==> 81 bytes
+ *
+ * assuming tunnel mode with AES encryption and integrity
+ * outer IP header : 20 bytes
+ * (NAT-T UDP header: 8 bytes)
+ * ESP header : 8 bytes
+ * IV : 16 bytes
+ * padding : 15 bytes (worst-case)
+ * pad len / NH : 2 bytes
+ * auth data : 12 bytes
+ */
+ strncpy(req.ifr_name, phys_name, IFNAMSIZ);
+ ioctl(sock, SIOCGIFMTU, &req);
+ mtu = req.ifr_mtu - 81;
+ }
+
+ /* set MTU */
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ req.ifr_mtu = mtu;
+ ioctl(sock, SIOCSIFMTU, &req);
+
+ /* bring ipsec device UP */
+ if (ioctl(sock, SIOCGIFFLAGS, &req) == 0)
+ {
+ req.ifr_flags |= IFF_UP;
+ ioctl(sock, SIOCSIFFLAGS, &req);
+ }
+
+ close(sock);
+ return SUCCESS;
+}
+
+/**
+ * detach an ipsec device from a physical interface
+ */
+static status_t detach_ipsec_dev(char* name, char *phys_name)
+{
+ int sock;
+ struct ifreq req;
+
+ DBG2(DBG_KNL, "detaching virtual interface %s from %s", name,
+ strlen(phys_name) ? phys_name : "any physical interface");
+
+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) <= 0)
+ {
+ return FAILED;
+ }
+
+ strncpy(req.ifr_name, name, IFNAMSIZ);
+ if (ioctl(sock, SIOCGIFFLAGS, &req) < 0)
+ {
+ close(sock);
+ return FAILED;
+ }
+
+ /* shutting interface down */
+ if (req.ifr_flags & IFF_UP)
+ {
+ req.ifr_flags &= ~IFF_UP;
+ ioctl(sock, SIOCSIFFLAGS, &req);
+ }
+
+ /* unset address */
+ memset(&req.ifr_addr, 0, sizeof(req.ifr_addr));
+ req.ifr_addr.sa_family = AF_INET;
+ ioctl(sock, SIOCSIFADDR, &req);
+
+ /* detach interface */
+ ioctl(sock, IPSEC_DEL_DEV, &req);
+
+ close(sock);
+ return SUCCESS;
+}
+
+/**
+ * destroy an ipsec_dev_t object
+ */
+static void ipsec_dev_destroy(ipsec_dev_t *this)
+{
+ detach_ipsec_dev(this->name, this->phys_name);
+ free(this);
+}
+
+
+typedef struct route_entry_t route_entry_t;
+
+/**
+ * installed routing entry
+ */
+struct route_entry_t {
+ /** Name of the interface the route is bound to */
+ char *if_name;
+
+ /** Source ip of the route */
+ host_t *src_ip;
+
+ /** Gateway for this route */
+ host_t *gateway;
+
+ /** Destination net */
+ chunk_t dst_net;
+
+ /** Destination net prefixlen */
+ u_int8_t prefixlen;
+};
+
+/**
+ * destroy an route_entry_t object
+ */
+static void route_entry_destroy(route_entry_t *this)
+{
+ free(this->if_name);
+ this->src_ip->destroy(this->src_ip);
+ this->gateway->destroy(this->gateway);
+ chunk_free(&this->dst_net);
+ free(this);
+}
+
+typedef struct policy_entry_t policy_entry_t;
+
+/**
+ * installed kernel policy.
+ */
+struct policy_entry_t {
+
+ /** reqid of this policy, if setup as trap */
+ u_int32_t reqid;
+
+ /** direction of this policy: in, out, forward */
+ u_int8_t direction;
+
+ /** parameters of installed policy */
+ struct {
+ /** subnet and port */
+ host_t *net;
+ /** subnet mask */
+ u_int8_t mask;
+ /** protocol */
+ u_int8_t proto;
+ } src, dst;
+
+ /** associated route installed for this policy */
+ route_entry_t *route;
+
+ /** by how many CHILD_SA's this policy is actively used */
+ u_int activecount;
+
+ /** by how many CHILD_SA's this policy is trapped */
+ u_int trapcount;
+};
+
+/**
+ * convert a numerical netmask to a host_t
+ */
+static host_t *mask2host(int family, u_int8_t mask)
+{
+ static const u_char bitmask[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
+ chunk_t chunk = chunk_alloca(family == AF_INET ? 4 : 16);
+ int bytes = mask / 8, bits = mask % 8;
+ memset(chunk.ptr, 0xFF, bytes);
+ memset(chunk.ptr + bytes, 0, chunk.len - bytes);
+ if (bits)
+ {
+ chunk.ptr[bytes] = bitmask[bits];
+ }
+ return host_create_from_chunk(family, chunk, 0);
+}
+
+/**
+ * check if a host is in a subnet (host with netmask in bits)
+ */
+static bool is_host_in_net(host_t *host, host_t *net, u_int8_t mask)
+{
+ static const u_char bitmask[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
+ chunk_t host_chunk, net_chunk;
+ int bytes = mask / 8, bits = mask % 8;
+
+ host_chunk = host->get_address(host);
+ net_chunk = net->get_address(net);
+
+ if (host_chunk.len != net_chunk.len)
+ {
+ return FALSE;
+ }
+
+ if (memeq(host_chunk.ptr, net_chunk.ptr, bytes))
+ {
+ return (bits == 0) ||
+ (host_chunk.ptr[bytes] & bitmask[bits]) ==
+ (net_chunk.ptr[bytes] & bitmask[bits]);
+ }
+
+ return FALSE;
+}
+
+/**
+ * create a policy_entry_t object
+ */
+static policy_entry_t *create_policy_entry(traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t dir)
+{
+ policy_entry_t *policy = malloc_thing(policy_entry_t);
+ policy->reqid = 0;
+ policy->direction = dir;
+ policy->route = NULL;
+ policy->activecount = 0;
+ policy->trapcount = 0;
+
+ src_ts->to_subnet(src_ts, &policy->src.net, &policy->src.mask);
+ dst_ts->to_subnet(dst_ts, &policy->dst.net, &policy->dst.mask);
+
+ /* src or dest proto may be "any" (0), use more restrictive one */
+ policy->src.proto = max(src_ts->get_protocol(src_ts), dst_ts->get_protocol(dst_ts));
+ policy->src.proto = policy->src.proto ? policy->src.proto : 0;
+ policy->dst.proto = policy->src.proto;
+
+ return policy;
+}
+
+/**
+ * destroy a policy_entry_t object
+ */
+static void policy_entry_destroy(policy_entry_t *this)
+{
+ DESTROY_IF(this->src.net);
+ DESTROY_IF(this->dst.net);
+ if (this->route)
+ {
+ route_entry_destroy(this->route);
+ }
+ free(this);
+}
+
+/**
+ * compares two policy_entry_t
+ */
+static inline bool policy_entry_equals(policy_entry_t *current, policy_entry_t *policy)
+{
+ return current->direction == policy->direction &&
+ current->src.proto == policy->src.proto &&
+ current->dst.proto == policy->dst.proto &&
+ current->src.mask == policy->src.mask &&
+ current->dst.mask == policy->dst.mask &&
+ current->src.net->equals(current->src.net, policy->src.net) &&
+ current->dst.net->equals(current->dst.net, policy->dst.net);
+}
+
+static inline bool policy_entry_match_byaddrs(policy_entry_t *current, host_t *src,
+ host_t *dst)
+{
+ return is_host_in_net(src, current->src.net, current->src.mask) &&
+ is_host_in_net(dst, current->dst.net, current->dst.mask);
+}
+
+typedef struct sa_entry_t sa_entry_t;
+
+/**
+ * used for two things:
+ * - allocated SPIs that have not yet resulted in an installed SA
+ * - installed inbound SAs with enabled UDP encapsulation
+ */
+struct sa_entry_t {
+
+ /** protocol of this SA */
+ protocol_id_t protocol;
+
+ /** reqid of this SA */
+ u_int32_t reqid;
+
+ /** SPI of this SA */
+ u_int32_t spi;
+
+ /** src address of this SA */
+ host_t *src;
+
+ /** dst address of this SA */
+ host_t *dst;
+
+ /** TRUE if this SA uses UDP encapsulation */
+ bool encap;
+
+ /** TRUE if this SA is inbound */
+ bool inbound;
+};
+
+/**
+ * create an sa_entry_t object
+ */
+static sa_entry_t *create_sa_entry(protocol_id_t protocol, u_int32_t spi,
+ u_int32_t reqid, host_t *src, host_t *dst,
+ bool encap, bool inbound)
+{
+ sa_entry_t *sa = malloc_thing(sa_entry_t);
+ sa->protocol = protocol;
+ sa->reqid = reqid;
+ sa->spi = spi;
+ sa->src = src ? src->clone(src) : NULL;
+ sa->dst = dst ? dst->clone(dst) : NULL;
+ sa->encap = encap;
+ sa->inbound = inbound;
+ return sa;
+}
+
+/**
+ * destroy an sa_entry_t object
+ */
+static void sa_entry_destroy(sa_entry_t *this)
+{
+ DESTROY_IF(this->src);
+ DESTROY_IF(this->dst);
+ free(this);
+}
+
+/**
+ * match an sa_entry_t for an inbound SA that uses UDP encapsulation by spi and src (remote) address
+ */
+static inline bool sa_entry_match_encapbysrc(sa_entry_t *current, u_int32_t *spi,
+ host_t *src)
+{
+ return current->encap && current->inbound &&
+ current->spi == *spi && src->ip_equals(src, current->src);
+}
+
+/**
+ * match an sa_entry_t by protocol, spi and dst address (as the kernel does it)
+ */
+static inline bool sa_entry_match_bydst(sa_entry_t *current, protocol_id_t *protocol,
+ u_int32_t *spi, host_t *dst)
+{
+ return current->protocol == *protocol && current->spi == *spi && dst->ip_equals(dst, current->dst);
+}
+
+/**
+ * match an sa_entry_t by protocol, reqid and spi
+ */
+static inline bool sa_entry_match_byid(sa_entry_t *current, protocol_id_t *protocol,
+ u_int32_t *spi, u_int32_t *reqid)
+{
+ return current->protocol == *protocol && current->spi == *spi && current->reqid == *reqid;
+}
+
+typedef struct pfkey_msg_t pfkey_msg_t;
+
+struct pfkey_msg_t
+{
+ /**
+ * PF_KEY message base
+ */
+ struct sadb_msg *msg;
+
+
+ /**
+ * PF_KEY message extensions
+ */
+ union {
+ struct sadb_ext *ext[SADB_EXT_MAX + 1];
+ struct {
+ struct sadb_ext *reserved; /* SADB_EXT_RESERVED */
+ struct sadb_sa *sa; /* SADB_EXT_SA */
+ struct sadb_lifetime *lft_current; /* SADB_EXT_LIFETIME_CURRENT */
+ struct sadb_lifetime *lft_hard; /* SADB_EXT_LIFETIME_HARD */
+ struct sadb_lifetime *lft_soft; /* SADB_EXT_LIFETIME_SOFT */
+ struct sadb_address *src; /* SADB_EXT_ADDRESS_SRC */
+ struct sadb_address *dst; /* SADB_EXT_ADDRESS_DST */
+ struct sadb_address *proxy; /* SADB_EXT_ADDRESS_PROXY */
+ struct sadb_key *key_auth; /* SADB_EXT_KEY_AUTH */
+ struct sadb_key *key_encr; /* SADB_EXT_KEY_ENCRYPT */
+ struct sadb_ident *id_src; /* SADB_EXT_IDENTITY_SRC */
+ struct sadb_ident *id_dst; /* SADB_EXT_IDENTITY_DST */
+ struct sadb_sens *sensitivity; /* SADB_EXT_SENSITIVITY */
+ struct sadb_prop *proposal; /* SADB_EXT_PROPOSAL */
+ struct sadb_supported *supported_auth; /* SADB_EXT_SUPPORTED_AUTH */
+ struct sadb_supported *supported_encr; /* SADB_EXT_SUPPORTED_ENCRYPT */
+ struct sadb_spirange *spirange; /* SADB_EXT_SPIRANGE */
+ struct sadb_x_kmprivate *x_kmprivate; /* SADB_X_EXT_KMPRIVATE */
+ struct sadb_ext *x_policy; /* SADB_X_EXT_SATYPE2 */
+ struct sadb_ext *x_sa2; /* SADB_X_EXT_SA2 */
+ struct sadb_address *x_dst2; /* SADB_X_EXT_ADDRESS_DST2 */
+ struct sadb_address *x_src_flow; /* SADB_X_EXT_ADDRESS_SRC_FLOW */
+ struct sadb_address *x_dst_flow; /* SADB_X_EXT_ADDRESS_DST_FLOW */
+ struct sadb_address *x_src_mask; /* SADB_X_EXT_ADDRESS_SRC_MASK */
+ struct sadb_address *x_dst_mask; /* SADB_X_EXT_ADDRESS_DST_MASK */
+ struct sadb_x_debug *x_debug; /* SADB_X_EXT_DEBUG */
+ struct sadb_protocol *x_protocol; /* SADB_X_EXT_PROTOCOL */
+ struct sadb_x_nat_t_type *x_natt_type; /* SADB_X_EXT_NAT_T_TYPE */
+ struct sadb_x_nat_t_port *x_natt_sport; /* SADB_X_EXT_NAT_T_SPORT */
+ struct sadb_x_nat_t_port *x_natt_dport; /* SADB_X_EXT_NAT_T_DPORT */
+ struct sadb_address *x_natt_oa; /* SADB_X_EXT_NAT_T_OA */
+ } __attribute__((__packed__));
+ };
+};
+
+/**
+ * convert a IKEv2 specific protocol identifier to the PF_KEY sa type
+ */
+static u_int8_t proto_ike2satype(protocol_id_t proto)
+{
+ switch (proto)
+ {
+ case PROTO_ESP:
+ return SADB_SATYPE_ESP;
+ case PROTO_AH:
+ return SADB_SATYPE_AH;
+ case IPPROTO_COMP:
+ return SADB_X_SATYPE_COMP;
+ default:
+ return proto;
+ }
+}
+
+/**
+ * convert a PF_KEY sa type to a IKEv2 specific protocol identifier
+ */
+static protocol_id_t proto_satype2ike(u_int8_t proto)
+{
+ switch (proto)
+ {
+ case SADB_SATYPE_ESP:
+ return PROTO_ESP;
+ case SADB_SATYPE_AH:
+ return PROTO_AH;
+ case SADB_X_SATYPE_COMP:
+ return IPPROTO_COMP;
+ default:
+ return proto;
+ }
+}
+
+typedef struct kernel_algorithm_t kernel_algorithm_t;
+
+/**
+ * Mapping of IKEv2 algorithms to PF_KEY algorithms
+ */
+struct kernel_algorithm_t {
+ /**
+ * Identifier specified in IKEv2
+ */
+ int ikev2;
+
+ /**
+ * Identifier as defined in pfkeyv2.h
+ */
+ int kernel;
+};
+
+#define END_OF_LIST -1
+
+/**
+ * Algorithms for encryption
+ */
+static kernel_algorithm_t encryption_algs[] = {
+/* {ENCR_DES_IV64, 0 }, */
+ {ENCR_DES, SADB_EALG_DESCBC },
+ {ENCR_3DES, SADB_EALG_3DESCBC },
+/* {ENCR_RC5, 0 }, */
+/* {ENCR_IDEA, 0 }, */
+/* {ENCR_CAST, 0 }, */
+ {ENCR_BLOWFISH, SADB_EALG_BFCBC },
+/* {ENCR_3IDEA, 0 }, */
+/* {ENCR_DES_IV32, 0 }, */
+ {ENCR_NULL, SADB_EALG_NULL },
+ {ENCR_AES_CBC, SADB_EALG_AESCBC },
+/* {ENCR_AES_CTR, 0 }, */
+/* {ENCR_AES_CCM_ICV8, 0 }, */
+/* {ENCR_AES_CCM_ICV12, 0 }, */
+/* {ENCR_AES_CCM_ICV16, 0 }, */
+/* {ENCR_AES_GCM_ICV8, 0 }, */
+/* {ENCR_AES_GCM_ICV12, 0 }, */
+/* {ENCR_AES_GCM_ICV16, 0 }, */
+ {END_OF_LIST, 0 },
+};
+
+/**
+ * Algorithms for integrity protection
+ */
+static kernel_algorithm_t integrity_algs[] = {
+ {AUTH_HMAC_MD5_96, SADB_AALG_MD5HMAC },
+ {AUTH_HMAC_SHA1_96, SADB_AALG_SHA1HMAC },
+ {AUTH_HMAC_SHA2_256_128, SADB_AALG_SHA256_HMAC },
+ {AUTH_HMAC_SHA2_384_192, SADB_AALG_SHA384_HMAC },
+ {AUTH_HMAC_SHA2_512_256, SADB_AALG_SHA512_HMAC },
+/* {AUTH_DES_MAC, 0, }, */
+/* {AUTH_KPDK_MD5, 0, }, */
+/* {AUTH_AES_XCBC_96, 0, }, */
+ {END_OF_LIST, 0, },
+};
+
+#if 0
+/**
+ * Algorithms for IPComp, unused yet
+ */
+static kernel_algorithm_t compression_algs[] = {
+/* {IPCOMP_OUI, 0 }, */
+ {IPCOMP_DEFLATE, SADB_X_CALG_DEFLATE },
+ {IPCOMP_LZS, SADB_X_CALG_LZS },
+/* {IPCOMP_LZJH, 0 }, */
+ {END_OF_LIST, 0 },
+};
+#endif
+
+/**
+ * Look up a kernel algorithm ID and its key size
+ */
+static int lookup_algorithm(kernel_algorithm_t *list, int ikev2)
+{
+ while (list->ikev2 != END_OF_LIST)
+ {
+ if (ikev2 == list->ikev2)
+ {
+ return list->kernel;
+ }
+ list++;
+ }
+ return 0;
+}
+
+/**
+ * add a host behind a sadb_address extension
+ */
+static void host2ext(host_t *host, struct sadb_address *ext)
+{
+ sockaddr_t *host_addr = host->get_sockaddr(host);
+ socklen_t *len = host->get_sockaddr_len(host);
+ memcpy((char*)(ext + 1), host_addr, *len);
+ ext->sadb_address_len = PFKEY_LEN(sizeof(*ext) + *len);
+}
+
+/**
+ * add a host behind a sadb_address extension
+ */
+static void add_addr_ext(struct sadb_msg *msg, host_t *host, u_int16_t type)
+{
+ struct sadb_address *addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+ addr->sadb_address_exttype = type;
+ host2ext(host, addr);
+ PFKEY_EXT_ADD(msg, addr);
+}
+
+/**
+ * adds an empty address extension to the given sadb_msg
+ */
+static void add_anyaddr_ext(struct sadb_msg *msg, int family, u_int8_t type)
+{
+ socklen_t len = (family == AF_INET) ? sizeof(struct sockaddr_in) :
+ sizeof(struct sockaddr_in6);
+ struct sadb_address *addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+ addr->sadb_address_exttype = type;
+ sockaddr_t *saddr = (sockaddr_t*)(addr + 1);
+ saddr->sa_family = family;
+ addr->sadb_address_len = PFKEY_LEN(sizeof(*addr) + len);
+ PFKEY_EXT_ADD(msg, addr);
+}
+
+/**
+ * add udp encap extensions to a sadb_msg
+ */
+static void add_encap_ext(struct sadb_msg *msg, host_t *src, host_t *dst,
+ bool ports_only)
+{
+ struct sadb_x_nat_t_type* nat_type;
+ struct sadb_x_nat_t_port* nat_port;
+
+ if (!ports_only)
+ {
+ nat_type = (struct sadb_x_nat_t_type*)PFKEY_EXT_ADD_NEXT(msg);
+ nat_type->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
+ nat_type->sadb_x_nat_t_type_len = PFKEY_LEN(sizeof(struct sadb_x_nat_t_type));
+ nat_type->sadb_x_nat_t_type_type = UDP_ENCAP_ESPINUDP;
+ PFKEY_EXT_ADD(msg, nat_type);
+ }
+
+ nat_port = (struct sadb_x_nat_t_port*)PFKEY_EXT_ADD_NEXT(msg);
+ nat_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_SPORT;
+ nat_port->sadb_x_nat_t_port_len = PFKEY_LEN(sizeof(struct sadb_x_nat_t_port));
+ nat_port->sadb_x_nat_t_port_port = src->get_port(src);
+ PFKEY_EXT_ADD(msg, nat_port);
+
+ nat_port = (struct sadb_x_nat_t_port*)PFKEY_EXT_ADD_NEXT(msg);
+ nat_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_DPORT;
+ nat_port->sadb_x_nat_t_port_len = PFKEY_LEN(sizeof(struct sadb_x_nat_t_port));
+ nat_port->sadb_x_nat_t_port_port = dst->get_port(dst);
+ PFKEY_EXT_ADD(msg, nat_port);
+}
+
+/**
+ * build an SADB_X_ADDFLOW msg
+ */
+static void build_addflow(struct sadb_msg *msg, u_int8_t satype, u_int32_t spi,
+ host_t *src, host_t *dst, host_t *src_net, u_int8_t src_mask,
+ host_t *dst_net, u_int8_t dst_mask, u_int8_t protocol, bool replace)
+{
+ struct sadb_sa *sa;
+ struct sadb_protocol *proto;
+ host_t *host;
+
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_X_ADDFLOW;
+ msg->sadb_msg_satype = satype;
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_spi = spi;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_flags = replace ? SADB_X_SAFLAGS_REPLACEFLOW : 0;
+ PFKEY_EXT_ADD(msg, sa);
+
+ if (!src)
+ {
+ add_anyaddr_ext(msg, src_net->get_family(src_net), SADB_EXT_ADDRESS_SRC);
+ }
+ else
+ {
+ add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC);
+ }
+
+ if (!dst)
+ {
+ add_anyaddr_ext(msg, dst_net->get_family(dst_net), SADB_EXT_ADDRESS_DST);
+ }
+ else
+ {
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST);
+ }
+
+ add_addr_ext(msg, src_net, SADB_X_EXT_ADDRESS_SRC_FLOW);
+ add_addr_ext(msg, dst_net, SADB_X_EXT_ADDRESS_DST_FLOW);
+
+ host = mask2host(src_net->get_family(src_net), src_mask);
+ add_addr_ext(msg, host, SADB_X_EXT_ADDRESS_SRC_MASK);
+ host->destroy(host);
+
+ host = mask2host(dst_net->get_family(dst_net), dst_mask);
+ add_addr_ext(msg, host, SADB_X_EXT_ADDRESS_DST_MASK);
+ host->destroy(host);
+
+ proto = (struct sadb_protocol*)PFKEY_EXT_ADD_NEXT(msg);
+ proto->sadb_protocol_exttype = SADB_X_EXT_PROTOCOL;
+ proto->sadb_protocol_len = PFKEY_LEN(sizeof(struct sadb_protocol));
+ proto->sadb_protocol_proto = protocol;
+ PFKEY_EXT_ADD(msg, proto);
+}
+
+/**
+ * build an SADB_X_DELFLOW msg
+ */
+static void build_delflow(struct sadb_msg *msg, u_int8_t satype,
+ host_t *src_net, u_int8_t src_mask, host_t *dst_net, u_int8_t dst_mask,
+ u_int8_t protocol)
+{
+ struct sadb_protocol *proto;
+ host_t *host;
+
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_X_DELFLOW;
+ msg->sadb_msg_satype = satype;
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ add_addr_ext(msg, src_net, SADB_X_EXT_ADDRESS_SRC_FLOW);
+ add_addr_ext(msg, dst_net, SADB_X_EXT_ADDRESS_DST_FLOW);
+
+ host = mask2host(src_net->get_family(src_net),
+ src_mask);
+ add_addr_ext(msg, host, SADB_X_EXT_ADDRESS_SRC_MASK);
+ host->destroy(host);
+
+ host = mask2host(dst_net->get_family(dst_net),
+ dst_mask);
+ add_addr_ext(msg, host, SADB_X_EXT_ADDRESS_DST_MASK);
+ host->destroy(host);
+
+ proto = (struct sadb_protocol*)PFKEY_EXT_ADD_NEXT(msg);
+ proto->sadb_protocol_exttype = SADB_X_EXT_PROTOCOL;
+ proto->sadb_protocol_len = PFKEY_LEN(sizeof(struct sadb_protocol));
+ proto->sadb_protocol_proto = protocol;
+ PFKEY_EXT_ADD(msg, proto);
+}
+
+/**
+ * Parses a pfkey message received from the kernel
+ */
+static status_t parse_pfkey_message(struct sadb_msg *msg, pfkey_msg_t *out)
+{
+ struct sadb_ext* ext;
+ size_t len;
+
+ memset(out, 0, sizeof(pfkey_msg_t));
+ out->msg = msg;
+
+ len = msg->sadb_msg_len;
+ len -= PFKEY_LEN(sizeof(struct sadb_msg));
+
+ ext = (struct sadb_ext*)(((char*)msg) + sizeof(struct sadb_msg));
+
+ while (len >= PFKEY_LEN(sizeof(struct sadb_ext)))
+ {
+ if (ext->sadb_ext_len < PFKEY_LEN(sizeof(struct sadb_ext)) ||
+ ext->sadb_ext_len > len)
+ {
+ DBG1(DBG_KNL, "length of PF_KEY extension (%d) is invalid", ext->sadb_ext_type);
+ break;
+ }
+
+ if ((ext->sadb_ext_type > SADB_EXT_MAX) || (!ext->sadb_ext_type))
+ {
+ DBG1(DBG_KNL, "type of PF_KEY extension (%d) is invalid", ext->sadb_ext_type);
+ break;
+ }
+
+ if (out->ext[ext->sadb_ext_type])
+ {
+ DBG1(DBG_KNL, "duplicate PF_KEY extension of type (%d)", ext->sadb_ext_type);
+ break;
+ }
+
+ out->ext[ext->sadb_ext_type] = ext;
+ ext = PFKEY_EXT_NEXT_LEN(ext, len);
+ }
+
+ if (len)
+ {
+ DBG1(DBG_KNL, "PF_KEY message length is invalid");
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Send a message to a specific PF_KEY socket and handle the response.
+ */
+static status_t pfkey_send_socket(private_kernel_klips_ipsec_t *this, int socket,
+ struct sadb_msg *in, struct sadb_msg **out, size_t *out_len)
+{
+ unsigned char buf[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg;
+ int in_len, len;
+
+ this->mutex_pfkey->lock(this->mutex_pfkey);
+
+ in->sadb_msg_seq = ++this->seq;
+ in->sadb_msg_pid = getpid();
+
+ in_len = PFKEY_USER_LEN(in->sadb_msg_len);
+
+ while (TRUE)
+ {
+ len = send(socket, in, in_len, 0);
+
+ if (len != in_len)
+ {
+ switch (errno)
+ {
+ case EINTR:
+ /* interrupted, try again */
+ continue;
+ case EINVAL:
+ case EEXIST:
+ case ESRCH:
+ /* we should also get a response for these from KLIPS */
+ break;
+ default:
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+ DBG1(DBG_KNL, "error sending to PF_KEY socket: %s (%d)",
+ strerror(errno), errno);
+ return FAILED;
+ }
+ }
+ break;
+ }
+
+ while (TRUE)
+ {
+ msg = (struct sadb_msg*)buf;
+
+ len = recv(socket, buf, sizeof(buf), 0);
+
+ if (len < 0)
+ {
+ if (errno == EINTR)
+ {
+ DBG1(DBG_KNL, "got interrupted");
+ /* interrupted, try again */
+ continue;
+ }
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+ DBG1(DBG_KNL, "error reading from PF_KEY socket: %s", strerror(errno));
+ return FAILED;
+ }
+ if (len < sizeof(struct sadb_msg) ||
+ msg->sadb_msg_len < PFKEY_LEN(sizeof(struct sadb_msg)))
+ {
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+ DBG1(DBG_KNL, "received corrupted PF_KEY message");
+ return FAILED;
+ }
+ if (msg->sadb_msg_len > len / PFKEY_ALIGNMENT)
+ {
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+ DBG1(DBG_KNL, "buffer was too small to receive the complete PF_KEY message");
+ return FAILED;
+ }
+ if (msg->sadb_msg_pid != in->sadb_msg_pid)
+ {
+ DBG2(DBG_KNL, "received PF_KEY message is not intended for us");
+ continue;
+ }
+ if (msg->sadb_msg_seq != this->seq)
+ {
+ DBG1(DBG_KNL, "received PF_KEY message with invalid sequence number,"
+ " was %d expected %d", msg->sadb_msg_seq, this->seq);
+ if (msg->sadb_msg_seq < this->seq)
+ {
+ continue;
+ }
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+ return FAILED;
+ }
+ if (msg->sadb_msg_type != in->sadb_msg_type)
+ {
+ DBG2(DBG_KNL, "received PF_KEY message of wrong type,"
+ " was %d expected %d, ignoring",
+ msg->sadb_msg_type, in->sadb_msg_type);
+ }
+ break;
+ }
+
+ *out_len = len;
+ *out = (struct sadb_msg*)malloc(len);
+ memcpy(*out, buf, len);
+
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+
+ return SUCCESS;
+}
+
+/**
+ * Send a message to the default PF_KEY socket.
+ */
+static status_t pfkey_send(private_kernel_klips_ipsec_t *this,
+ struct sadb_msg *in, struct sadb_msg **out, size_t *out_len)
+{
+ return pfkey_send_socket(this, this->socket, in, out, out_len);
+}
+
+/**
+ * Send a message to the default PF_KEY socket and handle the response.
+ */
+static status_t pfkey_send_ack(private_kernel_klips_ipsec_t *this, struct sadb_msg *in)
+{
+ struct sadb_msg *out;
+ size_t len;
+
+ if (pfkey_send(this, in, &out, &len) != SUCCESS)
+ {
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "PF_KEY error: %s (%d)",
+ strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+ return SUCCESS;
+}
+
+/**
+ * Add an eroute to KLIPS
+ */
+static status_t add_eroute(private_kernel_klips_ipsec_t *this, u_int8_t satype,
+ u_int32_t spi, host_t *src, host_t *dst, host_t *src_net, u_int8_t src_mask,
+ host_t *dst_net, u_int8_t dst_mask, u_int8_t protocol, bool replace)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg = (struct sadb_msg*)request;
+
+ memset(&request, 0, sizeof(request));
+
+ build_addflow(msg, satype, spi, src, dst, src_net, src_mask,
+ dst_net, dst_mask, protocol, replace);
+
+ return pfkey_send_ack(this, msg);
+}
+
+/**
+ * Delete an eroute fom KLIPS
+ */
+static status_t del_eroute(private_kernel_klips_ipsec_t *this, u_int8_t satype,
+ host_t *src_net, u_int8_t src_mask, host_t *dst_net, u_int8_t dst_mask,
+ u_int8_t protocol)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg = (struct sadb_msg*)request;
+
+ memset(&request, 0, sizeof(request));
+
+ build_delflow(msg, satype, src_net, src_mask, dst_net, dst_mask, protocol);
+
+ return pfkey_send_ack(this, msg);
+}
+
+/**
+ * Process a SADB_ACQUIRE message from the kernel
+ */
+static void process_acquire(private_kernel_klips_ipsec_t *this, struct sadb_msg* msg)
+{
+ pfkey_msg_t response;
+ host_t *src, *dst;
+ u_int32_t reqid;
+ u_int8_t proto;
+ policy_entry_t *policy;
+ job_t *job;
+
+ switch (msg->sadb_msg_satype)
+ {
+ case SADB_SATYPE_UNSPEC:
+ case SADB_SATYPE_ESP:
+ case SADB_SATYPE_AH:
+ break;
+ default:
+ /* acquire for AH/ESP only */
+ return;
+ }
+
+ if (parse_pfkey_message(msg, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "parsing SADB_ACQUIRE from kernel failed");
+ return;
+ }
+
+ /* KLIPS provides us only with the source and destination address,
+ * and the transport protocol of the packet that triggered the policy.
+ * we use this information to find a matching policy in our cache.
+ * because KLIPS installs a narrow %hold eroute covering only this information,
+ * we replace both the %trap and this %hold eroutes with a broader %hold
+ * eroute covering the whole policy */
+ src = host_create_from_sockaddr((sockaddr_t*)(response.src + 1));
+ dst = host_create_from_sockaddr((sockaddr_t*)(response.dst + 1));
+ proto = response.src->sadb_address_proto;
+ if (!src || !dst || src->get_family(src) != dst->get_family(dst))
+ {
+ DBG1(DBG_KNL, "received an SADB_ACQUIRE with invalid hosts");
+ return;
+ }
+
+ DBG2(DBG_KNL, "received an SADB_ACQUIRE for %H == %H : %d", src, dst, proto);
+ this->mutex->lock(this->mutex);
+ if (this->policies->find_first(this->policies,
+ (linked_list_match_t)policy_entry_match_byaddrs,
+ (void**)&policy, src, dst) != SUCCESS)
+ {
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_KNL, "received an SADB_ACQUIRE, but found no matching policy");
+ return;
+ }
+ if ((reqid = policy->reqid) == 0)
+ {
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_KNL, "received an SADB_ACQUIRE, but policy is not routed anymore");
+ return;
+ }
+
+ /* add a broad %hold eroute that replaces the %trap eroute */
+ add_eroute(this, SADB_X_SATYPE_INT, htonl(SPI_HOLD), NULL, NULL,
+ policy->src.net, policy->src.mask, policy->dst.net, policy->dst.mask,
+ policy->src.proto, TRUE);
+
+ /* remove the narrow %hold eroute installed by KLIPS */
+ del_eroute(this, SADB_X_SATYPE_INT, src, 32, dst, 32, proto);
+
+ this->mutex->unlock(this->mutex);
+
+ DBG2(DBG_KNL, "received an SADB_ACQUIRE");
+ DBG1(DBG_KNL, "creating acquire job for CHILD_SA with reqid {%d}", reqid);
+ job = (job_t*)acquire_job_create(reqid, NULL, NULL);
+ charon->processor->queue_job(charon->processor, job);
+}
+
+/**
+ * Process a SADB_X_NAT_T_NEW_MAPPING message from the kernel
+ */
+static void process_mapping(private_kernel_klips_ipsec_t *this, struct sadb_msg* msg)
+{
+ pfkey_msg_t response;
+ u_int32_t spi, reqid;
+ host_t *old_src, *new_src;
+ job_t *job;
+
+ DBG2(DBG_KNL, "received an SADB_X_NAT_T_NEW_MAPPING");
+
+ if (parse_pfkey_message(msg, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "parsing SADB_X_NAT_T_NEW_MAPPING from kernel failed");
+ return;
+ }
+
+ spi = response.sa->sadb_sa_spi;
+
+ if (proto_satype2ike(msg->sadb_msg_satype) == PROTO_ESP)
+ {
+ sa_entry_t *sa;
+ sockaddr_t *addr = (sockaddr_t*)(response.src + 1);
+ old_src = host_create_from_sockaddr(addr);
+
+ this->mutex->lock(this->mutex);
+ if (!old_src || this->installed_sas->find_first(this->installed_sas,
+ (linked_list_match_t)sa_entry_match_encapbysrc,
+ (void**)&sa, &spi, old_src) != SUCCESS)
+ {
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_KNL, "received an SADB_X_NAT_T_NEW_MAPPING, but found no matching SA");
+ return;
+ }
+ reqid = sa->reqid;
+ this->mutex->unlock(this->mutex);
+
+ addr = (sockaddr_t*)(response.dst + 1);
+ switch (addr->sa_family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in*)addr;
+ sin->sin_port = htons(response.x_natt_dport->sadb_x_nat_t_port_port);
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)addr;
+ sin6->sin6_port = htons(response.x_natt_dport->sadb_x_nat_t_port_port);
+ }
+ default:
+ break;
+ }
+ new_src = host_create_from_sockaddr(addr);
+ if (new_src)
+ {
+ DBG1(DBG_KNL, "NAT mappings of ESP CHILD_SA with SPI %.8x and"
+ " reqid {%d} changed, queuing update job", ntohl(spi), reqid);
+ job = (job_t*)update_sa_job_create(reqid, new_src);
+ charon->processor->queue_job(charon->processor, job);
+ }
+ }
+}
+
+/**
+ * Receives events from kernel
+ */
+static job_requeue_t receive_events(private_kernel_klips_ipsec_t *this)
+{
+ unsigned char buf[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg = (struct sadb_msg*)buf;
+ int len, oldstate;
+
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
+ len = recv(this->socket_events, buf, sizeof(buf), 0);
+ pthread_setcancelstate(oldstate, NULL);
+
+ if (len < 0)
+ {
+ switch (errno)
+ {
+ case EINTR:
+ /* interrupted, try again */
+ return JOB_REQUEUE_DIRECT;
+ case EAGAIN:
+ /* no data ready, select again */
+ return JOB_REQUEUE_DIRECT;
+ default:
+ DBG1(DBG_KNL, "unable to receive from PF_KEY event socket");
+ sleep(1);
+ return JOB_REQUEUE_FAIR;
+ }
+ }
+
+ if (len < sizeof(struct sadb_msg) ||
+ msg->sadb_msg_len < PFKEY_LEN(sizeof(struct sadb_msg)))
+ {
+ DBG2(DBG_KNL, "received corrupted PF_KEY message");
+ return JOB_REQUEUE_DIRECT;
+ }
+ if (msg->sadb_msg_pid != 0)
+ { /* not from kernel. not interested, try another one */
+ return JOB_REQUEUE_DIRECT;
+ }
+ if (msg->sadb_msg_len > len / PFKEY_ALIGNMENT)
+ {
+ DBG1(DBG_KNL, "buffer was too small to receive the complete PF_KEY message");
+ return JOB_REQUEUE_DIRECT;
+ }
+
+ switch (msg->sadb_msg_type)
+ {
+ case SADB_ACQUIRE:
+ process_acquire(this, msg);
+ break;
+ case SADB_EXPIRE:
+ /* SADB_EXPIRE events in KLIPS are only triggered by traffic (even for
+ * the time based limits). So if there is no traffic for a longer
+ * period than configured as hard limit, we wouldn't be able to rekey
+ * the SA and just receive the hard expire and thus delete the SA.
+ * To avoid this behavior and to make charon behave as with the other
+ * kernel plugins, we implement the expiration of SAs ourselves. */
+ break;
+ case SADB_X_NAT_T_NEW_MAPPING:
+ process_mapping(this, msg);
+ break;
+ default:
+ break;
+ }
+
+ return JOB_REQUEUE_DIRECT;
+}
+
+typedef enum {
+ /** an SPI has expired */
+ EXPIRE_TYPE_SPI,
+ /** a CHILD_SA has to be rekeyed */
+ EXPIRE_TYPE_SOFT,
+ /** a CHILD_SA has to be deleted */
+ EXPIRE_TYPE_HARD
+} expire_type_t;
+
+typedef struct sa_expire_t sa_expire_t;
+
+struct sa_expire_t {
+ /** kernel interface */
+ private_kernel_klips_ipsec_t *this;
+ /** the SPI of the expiring SA */
+ u_int32_t spi;
+ /** the protocol of the expiring SA */
+ protocol_id_t protocol;
+ /** the reqid of the expiring SA*/
+ u_int32_t reqid;
+ /** what type of expire this is */
+ expire_type_t type;
+};
+
+/**
+ * Called when an SA expires
+ */
+static job_requeue_t sa_expires(sa_expire_t *expire)
+{
+ private_kernel_klips_ipsec_t *this = expire->this;
+ protocol_id_t protocol = expire->protocol;
+ u_int32_t spi = expire->spi, reqid = expire->reqid;
+ bool hard = expire->type != EXPIRE_TYPE_SOFT;
+ sa_entry_t *cached_sa;
+ linked_list_t *list;
+ job_t *job;
+
+ /* for an expired SPI we first check whether the CHILD_SA got installed
+ * in the meantime, for expired SAs we check whether they are still installed */
+ list = expire->type == EXPIRE_TYPE_SPI ? this->allocated_spis : this->installed_sas;
+
+ this->mutex->lock(this->mutex);
+ if (list->find_first(list, (linked_list_match_t)sa_entry_match_byid,
+ (void**)&cached_sa, &protocol, &spi, &reqid) != SUCCESS)
+ {
+ /* we found no entry:
+ * - for SPIs, a CHILD_SA has been installed
+ * - for SAs, the CHILD_SA has already been deleted */
+ this->mutex->unlock(this->mutex);
+ return JOB_REQUEUE_NONE;
+ }
+ else
+ {
+ list->remove(list, cached_sa, NULL);
+ sa_entry_destroy(cached_sa);
+ }
+ this->mutex->unlock(this->mutex);
+
+ DBG2(DBG_KNL, "%N CHILD_SA with SPI %.8x and reqid {%d} expired",
+ protocol_id_names, protocol, ntohl(spi), reqid);
+
+ DBG1(DBG_KNL, "creating %s job for %N CHILD_SA with SPI %.8x and reqid {%d}",
+ hard ? "delete" : "rekey", protocol_id_names,
+ protocol, ntohl(spi), reqid);
+ if (hard)
+ {
+ job = (job_t*)delete_child_sa_job_create(reqid, protocol, spi);
+ }
+ else
+ {
+ job = (job_t*)rekey_child_sa_job_create(reqid, protocol, spi);
+ }
+ charon->processor->queue_job(charon->processor, job);
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Schedule an expire job for an SA. Time is in seconds.
+ */
+static void schedule_expire(private_kernel_klips_ipsec_t *this,
+ protocol_id_t protocol, u_int32_t spi,
+ u_int32_t reqid, expire_type_t type, u_int32_t time)
+{
+ callback_job_t *job;
+ sa_expire_t *expire = malloc_thing(sa_expire_t);
+ expire->this = this;
+ expire->protocol = protocol;
+ expire->spi = spi;
+ expire->reqid = reqid;
+ expire->type = type;
+ job = callback_job_create((callback_job_cb_t)sa_expires, expire, free, NULL);
+ charon->scheduler->schedule_job(charon->scheduler, (job_t*)job, time * 1000);
+}
+
+/**
+ * Implementation of kernel_interface_t.get_spi.
+ */
+static status_t get_spi(private_kernel_klips_ipsec_t *this,
+ host_t *src, host_t *dst,
+ protocol_id_t protocol, u_int32_t reqid,
+ u_int32_t *spi)
+{
+ /* we cannot use SADB_GETSPI because KLIPS does not allow us to set the
+ * NAT-T type in an SADB_UPDATE which we would have to use to update the
+ * implicitly created SA.
+ */
+ rng_t *rng;
+ u_int32_t spi_gen;
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ DBG1(DBG_KNL, "allocating SPI failed: no RNG");
+ return FAILED;
+ }
+ rng->get_bytes(rng, sizeof(spi_gen), (void*)&spi_gen);
+ rng->destroy(rng);
+
+ /* charon's SPIs lie within the range from 0xc0000000 to 0xcFFFFFFF */
+ spi_gen = 0xc0000000 | (spi_gen & 0x0FFFFFFF);
+
+ DBG2(DBG_KNL, "allocated SPI %.8x for %N SA between %#H..%#H",
+ spi_gen, protocol_id_names, protocol, src, dst);
+
+ *spi = htonl(spi_gen);
+
+ this->mutex->lock(this->mutex);
+ this->allocated_spis->insert_last(this->allocated_spis,
+ create_sa_entry(protocol, *spi, reqid, NULL, NULL, FALSE, TRUE));
+ this->mutex->unlock(this->mutex);
+ schedule_expire(this, protocol, *spi, reqid, EXPIRE_TYPE_SPI, SPI_TIMEOUT);
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.get_cpi.
+ */
+static status_t get_cpi(private_kernel_klips_ipsec_t *this,
+ host_t *src, host_t *dst,
+ u_int32_t reqid, u_int16_t *cpi)
+{
+ return FAILED;
+}
+
+/**
+ * Add a pseudo IPIP SA for tunnel mode with KLIPS.
+ */
+static status_t add_ipip_sa(private_kernel_klips_ipsec_t *this,
+ host_t *src, host_t *dst, u_int32_t spi, u_int32_t reqid)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_sa *sa;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "adding pseudo IPIP SA with SPI %.8x and reqid {%d}", ntohl(spi), reqid);
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_ADD;
+ msg->sadb_msg_satype = SADB_X_SATYPE_IPIP;
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_spi = spi;
+ sa->sadb_sa_state = SADB_SASTATE_MATURE;
+ PFKEY_EXT_ADD(msg, sa);
+
+ add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC);
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to add pseudo IPIP SA with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to add pseudo IPIP SA with SPI %.8x: %s (%d)",
+ ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+
+ free(out);
+ return SUCCESS;
+}
+
+/**
+ * group the IPIP SA required for tunnel mode with the outer SA
+ */
+static status_t group_ipip_sa(private_kernel_klips_ipsec_t *this,
+ host_t *src, host_t *dst, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_sa *sa;
+ struct sadb_x_satype *satype;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "grouping SAs with SPI %.8x and reqid {%d}", ntohl(spi), reqid);
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_X_GRPSA;
+ msg->sadb_msg_satype = SADB_X_SATYPE_IPIP;
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_spi = spi;
+ sa->sadb_sa_state = SADB_SASTATE_MATURE;
+ PFKEY_EXT_ADD(msg, sa);
+
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST);
+
+ satype = (struct sadb_x_satype*)PFKEY_EXT_ADD_NEXT(msg);
+ satype->sadb_x_satype_exttype = SADB_X_EXT_SATYPE2;
+ satype->sadb_x_satype_len = PFKEY_LEN(sizeof(struct sadb_x_satype));
+ satype->sadb_x_satype_satype = proto_ike2satype(protocol);
+ PFKEY_EXT_ADD(msg, satype);
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_X_EXT_SA2;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_spi = spi;
+ sa->sadb_sa_state = SADB_SASTATE_MATURE;
+ PFKEY_EXT_ADD(msg, sa);
+
+ add_addr_ext(msg, dst, SADB_X_EXT_ADDRESS_DST2);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to group SAs with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to group SAs with SPI %.8x: %s (%d)",
+ ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+
+ free(out);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.add_sa.
+ */
+static status_t add_sa(private_kernel_klips_ipsec_t *this,
+ host_t *src, host_t *dst, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid,
+ u_int64_t expire_soft, u_int64_t expire_hard,
+ u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key,
+ ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool encap, bool inbound)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_sa *sa;
+ struct sadb_key *key;
+ size_t len;
+
+ if (inbound)
+ {
+ /* for inbound SAs we allocated an SPI via get_spi, so we first check
+ * whether that SPI has already expired (race condition) */
+ sa_entry_t *alloc_spi;
+ this->mutex->lock(this->mutex);
+ if (this->allocated_spis->find_first(this->allocated_spis,
+ (linked_list_match_t)sa_entry_match_byid, (void**)&alloc_spi,
+ &protocol, &spi, &reqid) != SUCCESS)
+ {
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_KNL, "allocated SPI %.8x has already expired", ntohl(spi));
+ return FAILED;
+ }
+ else
+ {
+ this->allocated_spis->remove(this->allocated_spis, alloc_spi, NULL);
+ sa_entry_destroy(alloc_spi);
+ }
+ this->mutex->unlock(this->mutex);
+ }
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%d}", ntohl(spi), reqid);
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_ADD;
+ msg->sadb_msg_satype = proto_ike2satype(protocol);
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_spi = spi;
+ sa->sadb_sa_state = SADB_SASTATE_MATURE;
+ sa->sadb_sa_replay = (protocol == IPPROTO_COMP) ? 0 : 32;
+ sa->sadb_sa_auth = lookup_algorithm(integrity_algs, int_alg);
+ sa->sadb_sa_encrypt = lookup_algorithm(encryption_algs, enc_alg);
+ PFKEY_EXT_ADD(msg, sa);
+
+ add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC);
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST);
+
+ if (enc_alg != ENCR_UNDEFINED)
+ {
+ if (!sa->sadb_sa_encrypt)
+ {
+ DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
+ encryption_algorithm_names, enc_alg);
+ return FAILED;
+ }
+ DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
+ encryption_algorithm_names, enc_alg, enc_key.len * 8);
+
+ key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg);
+ key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
+ key->sadb_key_bits = enc_key.len * 8;
+ key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + enc_key.len);
+ memcpy(key + 1, enc_key.ptr, enc_key.len);
+
+ PFKEY_EXT_ADD(msg, key);
+ }
+
+ if (int_alg != AUTH_UNDEFINED)
+ {
+ if (!sa->sadb_sa_auth)
+ {
+ DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
+ integrity_algorithm_names, int_alg);
+ return FAILED;
+ }
+ DBG2(DBG_KNL, " using integrity algorithm %N with key size %d",
+ integrity_algorithm_names, int_alg, int_key.len * 8);
+
+ key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg);
+ key->sadb_key_exttype = SADB_EXT_KEY_AUTH;
+ key->sadb_key_bits = int_key.len * 8;
+ key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + int_key.len);
+ memcpy(key + 1, int_key.ptr, int_key.len);
+
+ PFKEY_EXT_ADD(msg, key);
+ }
+
+ if (ipcomp != IPCOMP_NONE)
+ {
+ /*TODO*/
+ }
+
+ if (encap)
+ {
+ add_encap_ext(msg, src, dst, FALSE);
+ }
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x: %s (%d)",
+ ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+
+ /* for tunnel mode SAs we have to install an additional IPIP SA and
+ * group the two SAs together */
+ if (mode == MODE_TUNNEL)
+ {
+ if (add_ipip_sa(this, src, dst, spi, reqid) != SUCCESS ||
+ group_ipip_sa(this, src, dst, spi, protocol, reqid) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ }
+
+ this->mutex->lock(this->mutex);
+ /* we cache this SA for two reasons:
+ * - in case an SADB_X_NAT_T_MAPPING_NEW event occurs (we need to find the reqid then)
+ * - to decide if an expired SA is still installed */
+ this->installed_sas->insert_last(this->installed_sas,
+ create_sa_entry(protocol, spi, reqid, src, dst, encap, inbound));
+ this->mutex->unlock(this->mutex);
+
+ /* Although KLIPS supports SADB_EXT_LIFETIME_SOFT/HARD, we handle the lifetime
+ * of SAs manually in the plugin. Refer to the comments in receive_events()
+ * for details. */
+ if (expire_soft)
+ {
+ schedule_expire(this, protocol, spi, reqid, EXPIRE_TYPE_SOFT, expire_soft);
+ }
+
+ if (expire_hard)
+ {
+ schedule_expire(this, protocol, spi, reqid, EXPIRE_TYPE_HARD, expire_hard);
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.update_sa.
+ */
+static status_t update_sa(private_kernel_klips_ipsec_t *this,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
+ host_t *src, host_t *dst,
+ host_t *new_src, host_t *new_dst,
+ bool encap, bool new_encap)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_sa *sa;
+ size_t len;
+
+ /* we can't update the SA if any of the ip addresses have changed.
+ * that's because we can't use SADB_UPDATE and by deleting and readding the
+ * SA the sequence numbers would get lost */
+ if (!src->ip_equals(src, new_src) ||
+ !dst->ip_equals(dst, new_dst))
+ {
+ DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: address changes"
+ " are not supported", ntohl(spi));
+ return NOT_SUPPORTED;
+ }
+
+ /* because KLIPS does not allow us to change the NAT-T type in an SADB_UPDATE,
+ * we can't update the SA if the encap flag has changed since installing it */
+ if (encap != new_encap)
+ {
+ DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: change of UDP"
+ " encapsulation is not supported", ntohl(spi));
+ return NOT_SUPPORTED;
+ }
+
+ DBG2(DBG_KNL, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H",
+ ntohl(spi), src, dst, new_src, new_dst);
+
+ memset(&request, 0, sizeof(request));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_UPDATE;
+ msg->sadb_msg_satype = proto_ike2satype(protocol);
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_spi = spi;
+ sa->sadb_sa_encrypt = SADB_EALG_AESCBC; /* ignored */
+ sa->sadb_sa_auth = SADB_AALG_SHA1HMAC; /* ignored */
+ sa->sadb_sa_state = SADB_SASTATE_MATURE;
+ PFKEY_EXT_ADD(msg, sa);
+
+ add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC);
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST);
+
+ add_encap_ext(msg, new_src, new_dst, TRUE);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: %s (%d)",
+ ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.del_sa.
+ */
+static status_t del_sa(private_kernel_klips_ipsec_t *this, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_sa *sa;
+ sa_entry_t *cached_sa;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ /* all grouped SAs are automatically deleted by KLIPS as soon as
+ * one of them is deleted, therefore we delete only the main one */
+ DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi));
+
+ this->mutex->lock(this->mutex);
+ /* this should not fail, but we don't care if it does, let the kernel decide
+ * whether this SA exists or not */
+ if (this->installed_sas->find_first(this->installed_sas,
+ (linked_list_match_t)sa_entry_match_bydst, (void**)&cached_sa,
+ &protocol, &spi, dst) == SUCCESS)
+ {
+ this->installed_sas->remove(this->installed_sas, cached_sa, NULL);
+ sa_entry_destroy(cached_sa);
+ }
+ this->mutex->unlock(this->mutex);
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_DELETE;
+ msg->sadb_msg_satype = proto_ike2satype(protocol);
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_spi = spi;
+ PFKEY_EXT_ADD(msg, sa);
+
+ /* the kernel wants an SADB_EXT_ADDRESS_SRC to be present even though
+ * it is not used for anything. */
+ add_anyaddr_ext(msg, dst->get_family(dst), SADB_EXT_ADDRESS_SRC);
+ add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x: %s (%d)",
+ ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+
+ DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi));
+ free(out);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.add_policy.
+ */
+static status_t add_policy(private_kernel_klips_ipsec_t *this,
+ host_t *src, host_t *dst,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid,
+ ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool routed)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ policy_entry_t *policy, *found = NULL;
+ u_int8_t satype;
+ size_t len;
+
+ if (direction == POLICY_FWD)
+ {
+ /* no forward policies for KLIPS */
+ return SUCCESS;
+ }
+
+ /* tunnel mode policies direct the packets into the pseudo IPIP SA */
+ satype = (mode == MODE_TUNNEL) ? SADB_X_SATYPE_IPIP :
+ proto_ike2satype(protocol);
+
+ /* create a policy */
+ policy = create_policy_entry(src_ts, dst_ts, direction);
+
+ /* find a matching policy */
+ this->mutex->lock(this->mutex);
+ if (this->policies->find_first(this->policies,
+ (linked_list_match_t)policy_entry_equals, (void**)&found, policy) == SUCCESS)
+ {
+ /* use existing policy */
+ DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing"
+ " refcount", src_ts, dst_ts,
+ policy_dir_names, direction);
+ policy_entry_destroy(policy);
+ policy = found;
+ }
+ else
+ {
+ /* apply the new one, if we have no such policy */
+ this->policies->insert_last(this->policies, policy);
+ }
+
+ if (routed)
+ {
+ /* we install this as a %trap eroute in the kernel, later to be
+ * triggered by packets matching the policy (-> ACQUIRE). */
+ spi = htonl(SPI_TRAP);
+ satype = SADB_X_SATYPE_INT;
+
+ /* the reqid is always set to the latest child SA that trapped this
+ * policy. we will need this reqid upon receiving an acquire. */
+ policy->reqid = reqid;
+
+ /* increase the trap counter */
+ policy->trapcount++;
+
+ if (policy->activecount)
+ {
+ /* we do not replace the current policy in the kernel while a
+ * policy is actively used */
+ this->mutex->unlock(this->mutex);
+ return SUCCESS;
+ }
+ }
+ else
+ {
+ /* increase the reference counter */
+ policy->activecount++;
+ }
+
+ DBG2(DBG_KNL, "adding policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+
+ memset(&request, 0, sizeof(request));
+
+ msg = (struct sadb_msg*)request;
+
+ /* FIXME: SADB_X_SAFLAGS_INFLOW may be required, if we add an inbound policy for an IPIP SA */
+ build_addflow(msg, satype, spi, routed ? NULL : src, routed ? NULL : dst,
+ policy->src.net, policy->src.mask, policy->dst.net, policy->dst.mask,
+ policy->src.proto, found != NULL);
+
+ this->mutex->unlock(this->mutex);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to add policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to add policy %R === %R %N: %s (%d)", src_ts, dst_ts,
+ policy_dir_names, direction,
+ strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+
+ this->mutex->lock(this->mutex);
+
+ /* we try to find the policy again and install the route if needed */
+ if (this->policies->find_last(this->policies, NULL, (void**)&policy) != SUCCESS)
+ {
+ this->mutex->unlock(this->mutex);
+ DBG2(DBG_KNL, "the policy %R === %R %N is already gone, ignoring",
+ src_ts, dst_ts, policy_dir_names, direction);
+ return SUCCESS;
+ }
+
+ /* KLIPS requires a special route that directs traffic that matches this
+ * policy to one of the virtual ipsec interfaces. The virtual interface
+ * has to be attached to the physical one the traffic runs over.
+ * This is a special case of the source route we install in other kernel
+ * interfaces.
+ * In the following cases we do NOT install a source route (but just a
+ * regular route):
+ * - we are not in tunnel mode
+ * - we are using IPv6 (does not work correctly yet!)
+ * - routing is disabled via strongswan.conf
+ */
+ if (policy->route == NULL && direction == POLICY_OUT)
+ {
+ char *iface;
+ ipsec_dev_t *dev;
+ route_entry_t *route = malloc_thing(route_entry_t);
+ route->src_ip = NULL;
+
+ if (mode != MODE_TRANSPORT && src->get_family(src) != AF_INET6 &&
+ this->install_routes)
+ {
+ charon->kernel_interface->get_address_by_ts(charon->kernel_interface,
+ src_ts, &route->src_ip);
+ }
+
+ if (!route->src_ip)
+ {
+ route->src_ip = host_create_any(src->get_family(src));
+ }
+
+ /* find the virtual interface */
+ iface = charon->kernel_interface->get_interface(charon->kernel_interface,
+ src);
+ if (find_ipsec_dev(this, iface, &dev) == SUCCESS)
+ {
+ /* above, we got either the name of a virtual or a physical
+ * interface. for both cases it means we already have the devices
+ * properly attached (assuming that we are exclusively attaching
+ * ipsec devices). */
+ dev->refcount++;
+ }
+ else
+ {
+ /* there is no record of a mapping with the returned interface.
+ * thus, we attach the first free virtual interface we find to
+ * it. As above we assume we are the only client fiddling with
+ * ipsec devices. */
+ if (this->ipsec_devices->find_first(this->ipsec_devices,
+ (linked_list_match_t)ipsec_dev_match_free,
+ (void**)&dev) == SUCCESS)
+ {
+ if (attach_ipsec_dev(dev->name, iface) == SUCCESS)
+ {
+ strncpy(dev->phys_name, iface, IFNAMSIZ);
+ dev->refcount = 1;
+ }
+ else
+ {
+ DBG1(DBG_KNL, "failed to attach virtual interface %s"
+ " to %s", dev->name, iface);
+ this->mutex->unlock(this->mutex);
+ free(iface);
+ return FAILED;
+ }
+ }
+ else
+ {
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_KNL, "failed to attach a virtual interface to %s: no"
+ " virtual interfaces left", iface);
+ free(iface);
+ return FAILED;
+ }
+ }
+ free(iface);
+ route->if_name = strdup(dev->name);
+
+ /* get the nexthop to dst */
+ route->gateway = charon->kernel_interface->get_nexthop(
+ charon->kernel_interface, dst);
+ route->dst_net = chunk_clone(policy->dst.net->get_address(policy->dst.net));
+ route->prefixlen = policy->dst.mask;
+
+ switch (charon->kernel_interface->add_route(charon->kernel_interface,
+ route->dst_net, route->prefixlen, route->gateway,
+ route->src_ip, route->if_name))
+ {
+ default:
+ DBG1(DBG_KNL, "unable to install route for policy %R === %R",
+ src_ts, dst_ts);
+ /* FALL */
+ case ALREADY_DONE:
+ /* route exists, do not uninstall */
+ route_entry_destroy(route);
+ break;
+ case SUCCESS:
+ /* cache the installed route */
+ policy->route = route;
+ break;
+ }
+ }
+
+ this->mutex->unlock(this->mutex);
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.query_policy.
+ */
+static status_t query_policy(private_kernel_klips_ipsec_t *this,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, u_int32_t *use_time)
+{
+ #define IDLE_PREFIX "idle="
+ static const char *path_eroute = "/proc/net/ipsec_eroute";
+ static const char *path_spi = "/proc/net/ipsec_spi";
+ FILE *file;
+ char line[1024], src[INET6_ADDRSTRLEN + 9], dst[INET6_ADDRSTRLEN + 9];
+ char *said = NULL, *pos;
+ policy_entry_t *policy, *found = NULL;
+ status_t status = FAILED;
+
+ if (direction == POLICY_FWD)
+ {
+ /* we do not install forward policies */
+ return FAILED;
+ }
+
+ DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+
+ /* create a policy */
+ policy = create_policy_entry(src_ts, dst_ts, direction);
+
+ /* find a matching policy */
+ this->mutex->lock(this->mutex);
+ if (this->policies->find_first(this->policies,
+ (linked_list_match_t)policy_entry_equals, (void**)&found, policy) != SUCCESS)
+ {
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_KNL, "querying policy %R === %R %N failed, not found", src_ts,
+ dst_ts, policy_dir_names, direction);
+ policy_entry_destroy(policy);
+ return NOT_FOUND;
+ }
+ policy_entry_destroy(policy);
+ policy = found;
+
+ /* src and dst selectors in KLIPS are of the form NET_ADDR/NETBITS:PROTO */
+ snprintf(src, sizeof(src), "%H/%d:%d", policy->src.net, policy->src.mask,
+ policy->src.proto);
+ src[sizeof(src) - 1] = '\0';
+ snprintf(dst, sizeof(dst), "%H/%d:%d", policy->dst.net, policy->dst.mask,
+ policy->dst.proto);
+ dst[sizeof(dst) - 1] = '\0';
+
+ this->mutex->unlock(this->mutex);
+
+ /* we try to find the matching eroute first */
+ file = fopen(path_eroute, "r");
+ if (file == NULL)
+ {
+ DBG1(DBG_KNL, "unable to query policy %R === %R %N: %s (%d)", src_ts,
+ dst_ts, policy_dir_names, direction, strerror(errno), errno);
+ return FAILED;
+ }
+
+ /* read line by line where each line looks like:
+ * packets src -> dst => said */
+ while (fgets(line, sizeof(line), file))
+ {
+ enumerator_t *enumerator;
+ char *token;
+ int i = 0;
+
+ enumerator = enumerator_create_token(line, " \t", " \t\n");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ switch (i++)
+ {
+ case 0: /* packets */
+ continue;
+ case 1: /* src */
+ if (streq(token, src))
+ {
+ continue;
+ }
+ break;
+ case 2: /* -> */
+ continue;
+ case 3: /* dst */
+ if (streq(token, dst))
+ {
+ continue;
+ }
+ break;
+ case 4: /* => */
+ continue;
+ case 5: /* said */
+ said = strdup(token);
+ break;
+ }
+ break;
+ }
+ enumerator->destroy(enumerator);
+
+ if (i == 5)
+ {
+ /* eroute matched */
+ break;
+ }
+ }
+ fclose(file);
+
+ if (said == NULL)
+ {
+ DBG1(DBG_KNL, "unable to query policy %R === %R %N: found no matching"
+ " eroute", src_ts, dst_ts, policy_dir_names, direction);
+ return FAILED;
+ }
+
+ /* compared with the one in the spi entry the SA ID from the eroute entry
+ * has an additional ":PROTO" appended, which we need to cut off */
+ pos = strrchr(said, ':');
+ *pos = '\0';
+
+ /* now we try to find the matching spi entry */
+ file = fopen(path_spi, "r");
+ if (file == NULL)
+ {
+ DBG1(DBG_KNL, "unable to query policy %R === %R %N: %s (%d)", src_ts,
+ dst_ts, policy_dir_names, direction, strerror(errno), errno);
+ return FAILED;
+ }
+
+ while (fgets(line, sizeof(line), file))
+ {
+ if (strneq(line, said, strlen(said)))
+ {
+ /* fine we found the correct line, now find the idle time */
+ u_int32_t idle_time;
+ pos = strstr(line, IDLE_PREFIX);
+ if (pos == NULL)
+ {
+ /* no idle time, i.e. this SA has not been used yet */
+ break;
+ }
+ if (sscanf(pos, IDLE_PREFIX"%u", &idle_time) <= 0)
+ {
+ /* idle time not valid */
+ break;
+ }
+
+ *use_time = time(NULL) - idle_time;
+ status = SUCCESS;
+ break;
+ }
+ }
+ fclose(file);
+ free(said);
+
+ return status;
+}
+
+/**
+ * Implementation of kernel_interface_t.del_policy.
+ */
+static status_t del_policy(private_kernel_klips_ipsec_t *this,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, bool unrouted)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg = (struct sadb_msg*)request, *out;
+ policy_entry_t *policy, *found = NULL;
+ route_entry_t *route;
+ size_t len;
+
+ if (direction == POLICY_FWD)
+ {
+ /* no forward policies for KLIPS */
+ return SUCCESS;
+ }
+
+ DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+
+ /* create a policy */
+ policy = create_policy_entry(src_ts, dst_ts, direction);
+
+ /* find a matching policy */
+ this->mutex->lock(this->mutex);
+ if (this->policies->find_first(this->policies,
+ (linked_list_match_t)policy_entry_equals, (void**)&found, policy) != SUCCESS)
+ {
+ this->mutex->unlock(this->mutex);
+ DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts,
+ dst_ts, policy_dir_names, direction);
+ policy_entry_destroy(policy);
+ return NOT_FOUND;
+ }
+ policy_entry_destroy(policy);
+
+ /* decrease appropriate counter */
+ unrouted ? found->trapcount-- : found->activecount--;
+
+ if (found->trapcount == 0)
+ {
+ /* if this policy is finally unrouted, we reset the reqid because it
+ * may still be actively used and there might be a pending acquire for
+ * this policy. */
+ found->reqid = 0;
+ }
+
+ if (found->activecount > 0)
+ {
+ /* is still used by SAs, keep in kernel */
+ this->mutex->unlock(this->mutex);
+ DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
+ return SUCCESS;
+ }
+ else if (found->activecount == 0 && found->trapcount > 0)
+ {
+ /* for a policy that is not used actively anymore, but is still trapped
+ * by another child SA we replace the current eroute with a %trap eroute */
+ DBG2(DBG_KNL, "policy still routed by another CHILD_SA, not removed");
+ memset(&request, 0, sizeof(request));
+ build_addflow(msg, SADB_X_SATYPE_INT, htonl(SPI_TRAP), NULL, NULL,
+ found->src.net, found->src.mask, found->dst.net,
+ found->dst.mask, found->src.proto, TRUE);
+ this->mutex->unlock(this->mutex);
+ return pfkey_send_ack(this, msg);
+ }
+
+ /* remove if last reference */
+ this->policies->remove(this->policies, found, NULL);
+ policy = found;
+
+ this->mutex->unlock(this->mutex);
+
+ memset(&request, 0, sizeof(request));
+
+ build_delflow(msg, 0, policy->src.net, policy->src.mask, policy->dst.net,
+ policy->dst.mask, policy->src.proto);
+
+ route = policy->route;
+ policy->route = NULL;
+ policy_entry_destroy(policy);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to delete policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to delete policy %R === %R %N: %s (%d)", src_ts,
+ dst_ts, policy_dir_names, direction,
+ strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+
+ if (route)
+ {
+ ipsec_dev_t *dev;
+
+ if (charon->kernel_interface->del_route(charon->kernel_interface,
+ route->dst_net, route->prefixlen, route->gateway,
+ route->src_ip, route->if_name) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "error uninstalling route installed with"
+ " policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ }
+
+ /* we have to detach the ipsec interface from the physical one over which
+ * this SA ran (if it is not used by any other) */
+ this->mutex->lock(this->mutex);
+
+ if (find_ipsec_dev(this, route->if_name, &dev) == SUCCESS)
+ {
+ /* fine, we found a matching device object, let's check if we have
+ * to detach it. */
+ if (--dev->refcount == 0)
+ {
+ if (detach_ipsec_dev(dev->name, dev->phys_name) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "failed to detach virtual interface %s"
+ " from %s", dev->name, dev->phys_name);
+ }
+ dev->phys_name[0] = '\0';
+ }
+ }
+
+ this->mutex->unlock(this->mutex);
+
+ route_entry_destroy(route);
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Initialize the list of ipsec devices
+ */
+static void init_ipsec_devices(private_kernel_klips_ipsec_t *this)
+{
+ int i, count = lib->settings->get_int(lib->settings,
+ "charon.plugins.kernel_klips.ipsec_dev_count",
+ DEFAULT_IPSEC_DEV_COUNT);
+
+ for (i = 0; i < count; ++i)
+ {
+ ipsec_dev_t *dev = malloc_thing(ipsec_dev_t);
+ snprintf(dev->name, IFNAMSIZ, IPSEC_DEV_PREFIX"%d", i);
+ dev->name[IFNAMSIZ - 1] = '\0';
+ dev->phys_name[0] = '\0';
+ dev->refcount = 0;
+ this->ipsec_devices->insert_last(this->ipsec_devices, dev);
+
+ /* detach any previously attached ipsec device */
+ detach_ipsec_dev(dev->name, dev->phys_name);
+ }
+}
+
+/**
+ * Register a socket for AQUIRE/EXPIRE messages
+ */
+static status_t register_pfkey_socket(private_kernel_klips_ipsec_t *this, u_int8_t satype)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_REGISTER;
+ msg->sadb_msg_satype = satype;
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ if (pfkey_send_socket(this, this->socket_events, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to register PF_KEY socket");
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to register PF_KEY socket: %s (%d)",
+ strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.destroy.
+ */
+static void destroy(private_kernel_klips_ipsec_t *this)
+{
+ this->job->cancel(this->job);
+ close(this->socket);
+ close(this->socket_events);
+ this->mutex_pfkey->destroy(this->mutex_pfkey);
+ this->mutex->destroy(this->mutex);
+ this->ipsec_devices->destroy_function(this->ipsec_devices, (void*)ipsec_dev_destroy);
+ this->installed_sas->destroy_function(this->installed_sas, (void*)sa_entry_destroy);
+ this->allocated_spis->destroy_function(this->allocated_spis, (void*)sa_entry_destroy);
+ this->policies->destroy_function(this->policies, (void*)policy_entry_destroy);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+kernel_klips_ipsec_t *kernel_klips_ipsec_create()
+{
+ private_kernel_klips_ipsec_t *this = malloc_thing(private_kernel_klips_ipsec_t);
+
+ /* public functions */
+ this->public.interface.get_spi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
+ this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
+ this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool))add_sa;
+ this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,u_int16_t,host_t*,host_t*,host_t*,host_t*,bool,bool))update_sa;
+ this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,u_int32_t,protocol_id_t,u_int16_t))del_sa;
+ this->public.interface.add_policy = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t,protocol_id_t,u_int32_t,ipsec_mode_t,u_int16_t,u_int16_t,bool))add_policy;
+ this->public.interface.query_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
+ this->public.interface.del_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,bool))del_policy;
+
+ this->public.interface.destroy = (void(*)(kernel_ipsec_t*)) destroy;
+
+ /* private members */
+ this->policies = linked_list_create();
+ this->allocated_spis = linked_list_create();
+ this->installed_sas = linked_list_create();
+ this->ipsec_devices = linked_list_create();
+ this->mutex = mutex_create(MUTEX_DEFAULT);
+ this->mutex_pfkey = mutex_create(MUTEX_DEFAULT);
+ this->install_routes = lib->settings->get_bool(lib->settings, "charon.install_routes", TRUE);
+ this->seq = 0;
+
+ /* initialize ipsec devices */
+ init_ipsec_devices(this);
+
+ /* create a PF_KEY socket to communicate with the kernel */
+ this->socket = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
+ if (this->socket <= 0)
+ {
+ charon->kill(charon, "unable to create PF_KEY socket");
+ }
+
+ /* create a PF_KEY socket for ACQUIRE & EXPIRE */
+ this->socket_events = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
+ if (this->socket_events <= 0)
+ {
+ charon->kill(charon, "unable to create PF_KEY event socket");
+ }
+
+ /* register the event socket */
+ if (register_pfkey_socket(this, SADB_SATYPE_ESP) != SUCCESS ||
+ register_pfkey_socket(this, SADB_SATYPE_AH) != SUCCESS)
+ {
+ charon->kill(charon, "unable to register PF_KEY event socket");
+ }
+
+ this->job = callback_job_create((callback_job_cb_t)receive_events,
+ this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+
+ return &this->public;
+}
diff --git a/src/charon/plugins/kernel_klips/kernel_klips_ipsec.h b/src/charon/plugins/kernel_klips/kernel_klips_ipsec.h
new file mode 100644
index 000000000..b16390ab4
--- /dev/null
+++ b/src/charon/plugins/kernel_klips/kernel_klips_ipsec.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * 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: kernel_klips_ipsec.h 4617 2008-11-11 08:45:19Z tobias $
+ */
+
+/**
+ * @defgroup kernel_klips_ipsec_i kernel_klips_ipsec
+ * @{ @ingroup kernel_klips
+ */
+
+#ifndef KERNEL_KLIPS_IPSEC_H_
+#define KERNEL_KLIPS_IPSEC_H_
+
+#include <kernel/kernel_ipsec.h>
+
+typedef struct kernel_klips_ipsec_t kernel_klips_ipsec_t;
+
+/**
+ * Implementation of the kernel ipsec interface using PF_KEY.
+ */
+struct kernel_klips_ipsec_t {
+
+ /**
+ * Implements kernel_ipsec_t interface
+ */
+ kernel_ipsec_t interface;
+};
+
+/**
+ * Create a PF_KEY kernel ipsec interface instance.
+ *
+ * @return kernel_klips_ipsec_t instance
+ */
+kernel_klips_ipsec_t *kernel_klips_ipsec_create();
+
+#endif /* KERNEL_KLIPS_IPSEC_H_ @} */
diff --git a/src/charon/plugins/kernel_klips/kernel_klips_plugin.c b/src/charon/plugins/kernel_klips/kernel_klips_plugin.c
new file mode 100644
index 000000000..42d7307ec
--- /dev/null
+++ b/src/charon/plugins/kernel_klips/kernel_klips_plugin.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * 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: kernel_klips_plugin.c 4617 2008-11-11 08:45:19Z tobias $
+ */
+
+
+#include "kernel_klips_plugin.h"
+
+#include "kernel_klips_ipsec.h"
+
+#include <daemon.h>
+
+typedef struct private_kernel_klips_plugin_t private_kernel_klips_plugin_t;
+
+/**
+ * private data of kernel PF_KEY plugin
+ */
+struct private_kernel_klips_plugin_t {
+ /**
+ * implements plugin interface
+ */
+ kernel_klips_plugin_t public;
+};
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_kernel_klips_plugin_t *this)
+{
+ charon->kernel_interface->remove_ipsec_interface(charon->kernel_interface, (kernel_ipsec_constructor_t)kernel_klips_ipsec_create);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *plugin_create()
+{
+ private_kernel_klips_plugin_t *this = malloc_thing(private_kernel_klips_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ charon->kernel_interface->add_ipsec_interface(charon->kernel_interface, (kernel_ipsec_constructor_t)kernel_klips_ipsec_create);
+
+ return &this->public.plugin;
+}
diff --git a/src/charon/plugins/kernel_klips/kernel_klips_plugin.h b/src/charon/plugins/kernel_klips/kernel_klips_plugin.h
new file mode 100644
index 000000000..67c3b74c6
--- /dev/null
+++ b/src/charon/plugins/kernel_klips/kernel_klips_plugin.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * 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: kernel_klips_plugin.h 4617 2008-11-11 08:45:19Z tobias $
+ */
+
+/**
+ * @defgroup kernel_klips kernel_klips
+ * @ingroup cplugins
+ *
+ * @defgroup kernel_klips_plugin kernel_klips_plugin
+ * @{ @ingroup kernel_klips
+ */
+
+#ifndef KERNEL_KLIPS_PLUGIN_H_
+#define KERNEL_KLIPS_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct kernel_klips_plugin_t kernel_klips_plugin_t;
+
+/**
+ * PF_KEY kernel interface plugin
+ */
+struct kernel_klips_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+/**
+ * Create a kernel_klips_plugin instance.
+ */
+plugin_t *plugin_create();
+
+#endif /* KERNEL_KLIPS_PLUGIN_H_ @} */
diff --git a/src/charon/plugins/kernel_klips/pfkeyv2.h b/src/charon/plugins/kernel_klips/pfkeyv2.h
new file mode 100644
index 000000000..78d3dfa91
--- /dev/null
+++ b/src/charon/plugins/kernel_klips/pfkeyv2.h
@@ -0,0 +1,322 @@
+/*
+RFC 2367 PF_KEY Key Management API July 1998
+
+
+Appendix D: Sample Header File
+
+This file defines structures and symbols for the PF_KEY Version 2
+key management interface. It was written at the U.S. Naval Research
+Laboratory. This file is in the public domain. The authors ask that
+you leave this credit intact on any copies of this file.
+*/
+#ifndef __PFKEY_V2_H
+#define __PFKEY_V2_H 1
+
+#define PF_KEY_V2 2
+#define PFKEYV2_REVISION 199806L
+
+#define SADB_RESERVED 0
+#define SADB_GETSPI 1
+#define SADB_UPDATE 2
+#define SADB_ADD 3
+#define SADB_DELETE 4
+#define SADB_GET 5
+#define SADB_ACQUIRE 6
+#define SADB_REGISTER 7
+#define SADB_EXPIRE 8
+#define SADB_FLUSH 9
+#define SADB_DUMP 10
+#define SADB_X_PROMISC 11
+#define SADB_X_PCHANGE 12
+#define SADB_X_GRPSA 13
+#define SADB_X_ADDFLOW 14
+#define SADB_X_DELFLOW 15
+#define SADB_X_DEBUG 16
+#define SADB_X_NAT_T_NEW_MAPPING 17
+#define SADB_MAX 17
+
+struct sadb_msg {
+ uint8_t sadb_msg_version;
+ uint8_t sadb_msg_type;
+ uint8_t sadb_msg_errno;
+ uint8_t sadb_msg_satype;
+ uint16_t sadb_msg_len;
+ uint16_t sadb_msg_reserved;
+ uint32_t sadb_msg_seq;
+ uint32_t sadb_msg_pid;
+};
+
+struct sadb_ext {
+ uint16_t sadb_ext_len;
+ uint16_t sadb_ext_type;
+};
+
+struct sadb_sa {
+ uint16_t sadb_sa_len;
+ uint16_t sadb_sa_exttype;
+ uint32_t sadb_sa_spi;
+ uint8_t sadb_sa_replay;
+ uint8_t sadb_sa_state;
+ uint8_t sadb_sa_auth;
+ uint8_t sadb_sa_encrypt;
+ uint32_t sadb_sa_flags;
+};
+
+struct sadb_lifetime {
+ uint16_t sadb_lifetime_len;
+ uint16_t sadb_lifetime_exttype;
+ uint32_t sadb_lifetime_allocations;
+ uint64_t sadb_lifetime_bytes;
+ uint64_t sadb_lifetime_addtime;
+ uint64_t sadb_lifetime_usetime;
+ uint32_t sadb_x_lifetime_packets;
+ uint32_t sadb_x_lifetime_reserved;
+};
+
+struct sadb_address {
+ uint16_t sadb_address_len;
+ uint16_t sadb_address_exttype;
+ uint8_t sadb_address_proto;
+ uint8_t sadb_address_prefixlen;
+ uint16_t sadb_address_reserved;
+};
+
+struct sadb_key {
+ uint16_t sadb_key_len;
+ uint16_t sadb_key_exttype;
+ uint16_t sadb_key_bits;
+ uint16_t sadb_key_reserved;
+};
+
+struct sadb_ident {
+ uint16_t sadb_ident_len;
+ uint16_t sadb_ident_exttype;
+ uint16_t sadb_ident_type;
+ uint16_t sadb_ident_reserved;
+ uint64_t sadb_ident_id;
+};
+
+struct sadb_sens {
+ uint16_t sadb_sens_len;
+ uint16_t sadb_sens_exttype;
+ uint32_t sadb_sens_dpd;
+ uint8_t sadb_sens_sens_level;
+ uint8_t sadb_sens_sens_len;
+ uint8_t sadb_sens_integ_level;
+ uint8_t sadb_sens_integ_len;
+ uint32_t sadb_sens_reserved;
+};
+
+struct sadb_prop {
+ uint16_t sadb_prop_len;
+ uint16_t sadb_prop_exttype;
+ uint8_t sadb_prop_replay;
+ uint8_t sadb_prop_reserved[3];
+};
+
+struct sadb_comb {
+ uint8_t sadb_comb_auth;
+ uint8_t sadb_comb_encrypt;
+ uint16_t sadb_comb_flags;
+ uint16_t sadb_comb_auth_minbits;
+ uint16_t sadb_comb_auth_maxbits;
+ uint16_t sadb_comb_encrypt_minbits;
+ uint16_t sadb_comb_encrypt_maxbits;
+ uint32_t sadb_comb_reserved;
+ uint32_t sadb_comb_soft_allocations;
+ uint32_t sadb_comb_hard_allocations;
+ uint64_t sadb_comb_soft_bytes;
+ uint64_t sadb_comb_hard_bytes;
+ uint64_t sadb_comb_soft_addtime;
+ uint64_t sadb_comb_hard_addtime;
+ uint64_t sadb_comb_soft_usetime;
+ uint64_t sadb_comb_hard_usetime;
+ uint32_t sadb_x_comb_soft_packets;
+ uint32_t sadb_x_comb_hard_packets;
+};
+
+struct sadb_supported {
+ uint16_t sadb_supported_len;
+ uint16_t sadb_supported_exttype;
+ uint32_t sadb_supported_reserved;
+};
+
+struct sadb_alg {
+ uint8_t sadb_alg_id;
+ uint8_t sadb_alg_ivlen;
+ uint16_t sadb_alg_minbits;
+ uint16_t sadb_alg_maxbits;
+ uint16_t sadb_alg_reserved;
+};
+
+struct sadb_spirange {
+ uint16_t sadb_spirange_len;
+ uint16_t sadb_spirange_exttype;
+ uint32_t sadb_spirange_min;
+ uint32_t sadb_spirange_max;
+ uint32_t sadb_spirange_reserved;
+};
+
+struct sadb_x_kmprivate {
+ uint16_t sadb_x_kmprivate_len;
+ uint16_t sadb_x_kmprivate_exttype;
+ uint32_t sadb_x_kmprivate_reserved;
+};
+
+struct sadb_x_satype {
+ uint16_t sadb_x_satype_len;
+ uint16_t sadb_x_satype_exttype;
+ uint8_t sadb_x_satype_satype;
+ uint8_t sadb_x_satype_reserved[3];
+};
+
+struct sadb_x_debug {
+ uint16_t sadb_x_debug_len;
+ uint16_t sadb_x_debug_exttype;
+ uint32_t sadb_x_debug_tunnel;
+ uint32_t sadb_x_debug_netlink;
+ uint32_t sadb_x_debug_xform;
+ uint32_t sadb_x_debug_eroute;
+ uint32_t sadb_x_debug_spi;
+ uint32_t sadb_x_debug_radij;
+ uint32_t sadb_x_debug_esp;
+ uint32_t sadb_x_debug_ah;
+ uint32_t sadb_x_debug_rcv;
+ uint32_t sadb_x_debug_pfkey;
+ uint32_t sadb_x_debug_ipcomp;
+ uint32_t sadb_x_debug_verbose;
+ uint8_t sadb_x_debug_reserved[4];
+};
+
+struct sadb_x_nat_t_type {
+ uint16_t sadb_x_nat_t_type_len;
+ uint16_t sadb_x_nat_t_type_exttype;
+ uint8_t sadb_x_nat_t_type_type;
+ uint8_t sadb_x_nat_t_type_reserved[3];
+};
+struct sadb_x_nat_t_port {
+ uint16_t sadb_x_nat_t_port_len;
+ uint16_t sadb_x_nat_t_port_exttype;
+ uint16_t sadb_x_nat_t_port_port;
+ uint16_t sadb_x_nat_t_port_reserved;
+};
+
+/*
+ * A protocol structure for passing through the transport level
+ * protocol. It contains more fields than are actually used/needed
+ * but it is this way to be compatible with the structure used in
+ * OpenBSD (http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/pfkeyv2.h)
+ */
+struct sadb_protocol {
+ uint16_t sadb_protocol_len;
+ uint16_t sadb_protocol_exttype;
+ uint8_t sadb_protocol_proto;
+ uint8_t sadb_protocol_direction;
+ uint8_t sadb_protocol_flags;
+ uint8_t sadb_protocol_reserved2;
+};
+
+#define SADB_EXT_RESERVED 0
+#define SADB_EXT_SA 1
+#define SADB_EXT_LIFETIME_CURRENT 2
+#define SADB_EXT_LIFETIME_HARD 3
+#define SADB_EXT_LIFETIME_SOFT 4
+#define SADB_EXT_ADDRESS_SRC 5
+#define SADB_EXT_ADDRESS_DST 6
+#define SADB_EXT_ADDRESS_PROXY 7
+#define SADB_EXT_KEY_AUTH 8
+#define SADB_EXT_KEY_ENCRYPT 9
+#define SADB_EXT_IDENTITY_SRC 10
+#define SADB_EXT_IDENTITY_DST 11
+#define SADB_EXT_SENSITIVITY 12
+#define SADB_EXT_PROPOSAL 13
+#define SADB_EXT_SUPPORTED_AUTH 14
+#define SADB_EXT_SUPPORTED_ENCRYPT 15
+#define SADB_EXT_SPIRANGE 16
+#define SADB_X_EXT_KMPRIVATE 17
+#define SADB_X_EXT_SATYPE2 18
+#define SADB_X_EXT_SA2 19
+#define SADB_X_EXT_ADDRESS_DST2 20
+#define SADB_X_EXT_ADDRESS_SRC_FLOW 21
+#define SADB_X_EXT_ADDRESS_DST_FLOW 22
+#define SADB_X_EXT_ADDRESS_SRC_MASK 23
+#define SADB_X_EXT_ADDRESS_DST_MASK 24
+#define SADB_X_EXT_DEBUG 25
+#define SADB_X_EXT_PROTOCOL 26
+#define SADB_X_EXT_NAT_T_TYPE 27
+#define SADB_X_EXT_NAT_T_SPORT 28
+#define SADB_X_EXT_NAT_T_DPORT 29
+#define SADB_X_EXT_NAT_T_OA 30
+#define SADB_EXT_MAX 30
+
+/* SADB_X_DELFLOW required over and above SADB_X_SAFLAGS_CLEARFLOW */
+#define SADB_X_EXT_ADDRESS_DELFLOW \
+ ( (1<<SADB_X_EXT_ADDRESS_SRC_FLOW) \
+ | (1<<SADB_X_EXT_ADDRESS_DST_FLOW) \
+ | (1<<SADB_X_EXT_ADDRESS_SRC_MASK) \
+ | (1<<SADB_X_EXT_ADDRESS_DST_MASK))
+
+#define SADB_SATYPE_UNSPEC 0
+#define SADB_SATYPE_AH 2
+#define SADB_SATYPE_ESP 3
+#define SADB_SATYPE_RSVP 5
+#define SADB_SATYPE_OSPFV2 6
+#define SADB_SATYPE_RIPV2 7
+#define SADB_SATYPE_MIP 8
+#define SADB_X_SATYPE_IPIP 9
+#define SADB_X_SATYPE_COMP 10
+#define SADB_X_SATYPE_INT 11
+#define SADB_SATYPE_MAX 11
+
+#define SADB_SASTATE_LARVAL 0
+#define SADB_SASTATE_MATURE 1
+#define SADB_SASTATE_DYING 2
+#define SADB_SASTATE_DEAD 3
+#define SADB_SASTATE_MAX 3
+
+#define SADB_SAFLAGS_PFS 1
+#define SADB_X_SAFLAGS_REPLACEFLOW 2
+#define SADB_X_SAFLAGS_CLEARFLOW 4
+#define SADB_X_SAFLAGS_INFLOW 8
+
+#define SADB_AALG_NONE 0
+#define SADB_AALG_MD5HMAC 2
+#define SADB_AALG_SHA1HMAC 3
+#define SADB_AALG_SHA256_HMAC 5
+#define SADB_AALG_SHA384_HMAC 6
+#define SADB_AALG_SHA512_HMAC 7
+#define SADB_AALG_RIPEMD160HMAC 8
+#define SADB_AALG_MAX 15
+
+#define SADB_EALG_NONE 0
+#define SADB_EALG_DESCBC 2
+#define SADB_EALG_3DESCBC 3
+#define SADB_EALG_BFCBC 7
+#define SADB_EALG_NULL 11
+#define SADB_EALG_AESCBC 12
+#define SADB_EALG_MAX 255
+
+#define SADB_X_CALG_NONE 0
+#define SADB_X_CALG_OUI 1
+#define SADB_X_CALG_DEFLATE 2
+#define SADB_X_CALG_LZS 3
+#define SADB_X_CALG_V42BIS 4
+#define SADB_X_CALG_MAX 4
+
+#define SADB_X_TALG_NONE 0
+#define SADB_X_TALG_IPv4_in_IPv4 1
+#define SADB_X_TALG_IPv6_in_IPv4 2
+#define SADB_X_TALG_IPv4_in_IPv6 3
+#define SADB_X_TALG_IPv6_in_IPv6 4
+#define SADB_X_TALG_MAX 4
+
+
+#define SADB_IDENTTYPE_RESERVED 0
+#define SADB_IDENTTYPE_PREFIX 1
+#define SADB_IDENTTYPE_FQDN 2
+#define SADB_IDENTTYPE_USERFQDN 3
+#define SADB_X_IDENTTYPE_CONNECTION 4
+#define SADB_IDENTTYPE_MAX 4
+
+#define SADB_KEY_FLAGS_MAX 0
+#endif /* __PFKEY_V2_H */
diff --git a/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c
index 7b78f9eb1..70a0b3e7c 100644
--- a/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2006-2008 Tobias Brunner
- * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2008 Andreas Steffen
* Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
@@ -16,17 +17,18 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: kernel_netlink_ipsec.c 4406 2008-10-10 08:36:01Z martin $
+ * $Id: kernel_netlink_ipsec.c 4662 2008-11-16 21:19:58Z andreas $
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
+#include <stdint.h>
+#include <linux/ipsec.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/xfrm.h>
#include <linux/udp.h>
-#include <netinet/in.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
@@ -36,9 +38,11 @@
#include "kernel_netlink_shared.h"
#include <daemon.h>
+#include <utils/mutex.h>
#include <utils/linked_list.h>
#include <processing/jobs/callback_job.h>
#include <processing/jobs/acquire_job.h>
+#include <processing/jobs/migrate_job.h>
#include <processing/jobs/rekey_child_sa_job.h>
#include <processing/jobs/delete_child_sa_job.h>
#include <processing/jobs/update_sa_job.h>
@@ -48,6 +52,11 @@
#define XFRM_STATE_AF_UNSPEC 32
#endif
+/** from linux/in.h */
+#ifndef IP_IPSEC_POLICY
+#define IP_IPSEC_POLICY 16
+#endif
+
/** default priority of installed policies */
#define PRIO_LOW 3000
#define PRIO_HIGH 2000
@@ -76,30 +85,41 @@
typedef struct kernel_algorithm_t kernel_algorithm_t;
/**
- * Mapping from the algorithms defined in IKEv2 to
- * kernel level algorithm names and their key length
+ * Mapping of IKEv2 kernel identifier to linux crypto API names
*/
struct kernel_algorithm_t {
/**
* Identifier specified in IKEv2
*/
- int ikev2_id;
+ int ikev2;
/**
- * Name of the algorithm, as used as kernel identifier
+ * Name of the algorithm in linux crypto API
*/
char *name;
-
- /**
- * Key length in bits, if fixed size
- */
- u_int key_size;
};
-ENUM(policy_dir_names, POLICY_IN, POLICY_FWD,
- "in",
- "out",
- "fwd"
+ENUM(xfrm_attr_type_names, XFRMA_UNSPEC, XFRMA_KMADDRESS,
+ "XFRMA_UNSPEC",
+ "XFRMA_ALG_AUTH",
+ "XFRMA_ALG_CRYPT",
+ "XFRMA_ALG_COMP",
+ "XFRMA_ENCAP",
+ "XFRMA_TMPL",
+ "XFRMA_SA",
+ "XFRMA_POLICY",
+ "XFRMA_SEC_CTX",
+ "XFRMA_LTIME_VAL",
+ "XFRMA_REPLAY_VAL",
+ "XFRMA_REPLAY_THRESH",
+ "XFRMA_ETIMER_THRESH",
+ "XFRMA_SRCADDR",
+ "XFRMA_COADDR",
+ "XFRMA_LASTUSED",
+ "XFRMA_POLICY_TYPE",
+ "XFRMA_MIGRATE",
+ "XFRMA_ALG_AEAD",
+ "XFRMA_KMADDRESS"
);
#define END_OF_LIST -1
@@ -108,71 +128,65 @@ ENUM(policy_dir_names, POLICY_IN, POLICY_FWD,
* Algorithms for encryption
*/
static kernel_algorithm_t encryption_algs[] = {
-/* {ENCR_DES_IV64, "***", 0}, */
- {ENCR_DES, "des", 64},
- {ENCR_3DES, "des3_ede", 192},
-/* {ENCR_RC5, "***", 0}, */
-/* {ENCR_IDEA, "***", 0}, */
- {ENCR_CAST, "cast128", 0},
- {ENCR_BLOWFISH, "blowfish", 0},
-/* {ENCR_3IDEA, "***", 0}, */
-/* {ENCR_DES_IV32, "***", 0}, */
- {ENCR_NULL, "cipher_null", 0},
- {ENCR_AES_CBC, "aes", 0},
-/* {ENCR_AES_CTR, "***", 0}, */
- {ENCR_AES_CCM_ICV8, "rfc4309(ccm(aes))", 64}, /* key_size = ICV size */
- {ENCR_AES_CCM_ICV12, "rfc4309(ccm(aes))", 96}, /* key_size = ICV size */
- {ENCR_AES_CCM_ICV16, "rfc4309(ccm(aes))", 128}, /* key_size = ICV size */
- {ENCR_AES_GCM_ICV8, "rfc4106(gcm(aes))", 64}, /* key_size = ICV size */
- {ENCR_AES_GCM_ICV12, "rfc4106(gcm(aes))", 96}, /* key_size = ICV size */
- {ENCR_AES_GCM_ICV16, "rfc4106(gcm(aes))", 128}, /* key_size = ICV size */
- {END_OF_LIST, NULL, 0},
+/* {ENCR_DES_IV64, "***" }, */
+ {ENCR_DES, "des" },
+ {ENCR_3DES, "des3_ede" },
+/* {ENCR_RC5, "***" }, */
+/* {ENCR_IDEA, "***" }, */
+ {ENCR_CAST, "cast128" },
+ {ENCR_BLOWFISH, "blowfish" },
+/* {ENCR_3IDEA, "***" }, */
+/* {ENCR_DES_IV32, "***" }, */
+ {ENCR_NULL, "cipher_null" },
+ {ENCR_AES_CBC, "aes" },
+/* {ENCR_AES_CTR, "***" }, */
+ {ENCR_AES_CCM_ICV8, "rfc4309(ccm(aes))" },
+ {ENCR_AES_CCM_ICV12, "rfc4309(ccm(aes))" },
+ {ENCR_AES_CCM_ICV16, "rfc4309(ccm(aes))" },
+ {ENCR_AES_GCM_ICV8, "rfc4106(gcm(aes))" },
+ {ENCR_AES_GCM_ICV12, "rfc4106(gcm(aes))" },
+ {ENCR_AES_GCM_ICV16, "rfc4106(gcm(aes))" },
+ {END_OF_LIST, NULL },
};
/**
* Algorithms for integrity protection
*/
static kernel_algorithm_t integrity_algs[] = {
- {AUTH_HMAC_MD5_96, "md5", 128},
- {AUTH_HMAC_SHA1_96, "sha1", 160},
- {AUTH_HMAC_SHA2_256_128, "sha256", 256},
- {AUTH_HMAC_SHA2_384_192, "sha384", 384},
- {AUTH_HMAC_SHA2_512_256, "sha512", 512},
-/* {AUTH_DES_MAC, "***", 0}, */
-/* {AUTH_KPDK_MD5, "***", 0}, */
- {AUTH_AES_XCBC_96, "xcbc(aes)", 128},
- {END_OF_LIST, NULL, 0},
+ {AUTH_HMAC_MD5_96, "md5" },
+ {AUTH_HMAC_SHA1_96, "sha1" },
+ {AUTH_HMAC_SHA2_256_128, "sha256" },
+ {AUTH_HMAC_SHA2_384_192, "sha384" },
+ {AUTH_HMAC_SHA2_512_256, "sha512" },
+/* {AUTH_DES_MAC, "***" }, */
+/* {AUTH_KPDK_MD5, "***" }, */
+ {AUTH_AES_XCBC_96, "xcbc(aes)" },
+ {END_OF_LIST, NULL },
};
/**
* Algorithms for IPComp
*/
static kernel_algorithm_t compression_algs[] = {
-/* {IPCOMP_OUI, "***", 0}, */
- {IPCOMP_DEFLATE, "deflate", 0},
- {IPCOMP_LZS, "lzs", 0},
- {IPCOMP_LZJH, "lzjh", 0},
- {END_OF_LIST, NULL, 0},
+/* {IPCOMP_OUI, "***" }, */
+ {IPCOMP_DEFLATE, "deflate" },
+ {IPCOMP_LZS, "lzs" },
+ {IPCOMP_LZJH, "lzjh" },
+ {END_OF_LIST, NULL },
};
/**
* Look up a kernel algorithm name and its key size
*/
-static char* lookup_algorithm(kernel_algorithm_t *kernel_algo,
- u_int16_t ikev2_algo, u_int16_t *key_size)
+static char* lookup_algorithm(kernel_algorithm_t *list, int ikev2)
{
- while (kernel_algo->ikev2_id != END_OF_LIST)
+ while (list->ikev2 != END_OF_LIST)
{
- if (ikev2_algo == kernel_algo->ikev2_id)
+ if (list->ikev2 == ikev2)
{
- /* match, evaluate key length */
- if (key_size && *key_size == 0)
- { /* update key size if not set */
- *key_size = kernel_algo->key_size;
- }
- return kernel_algo->name;
+ return list->name;
}
- kernel_algo++;
+ list++;
}
return NULL;
}
@@ -221,9 +235,6 @@ struct policy_entry_t {
/** direction of this policy: in, out, forward */
u_int8_t direction;
- /** reqid of the policy */
- u_int32_t reqid;
-
/** parameters of installed policy */
struct xfrm_selector sel;
@@ -248,7 +259,7 @@ struct private_kernel_netlink_ipsec_t {
/**
* mutex to lock access to various lists
*/
- pthread_mutex_t mutex;
+ mutex_t *mutex;
/**
* List of installed policies (policy_entry_t)
@@ -344,41 +355,13 @@ static host_t* xfrm2host(int family, xfrm_address_t *xfrm, u_int16_t port)
static void ts2subnet(traffic_selector_t* ts,
xfrm_address_t *net, u_int8_t *mask)
{
- /* there is no way to do this cleanly, as the address range may
- * be anything else but a subnet. We use from_addr as subnet
- * and try to calculate a usable subnet mask.
- */
- int byte, bit;
- bool found = FALSE;
- chunk_t from, to;
- size_t size = (ts->get_type(ts) == TS_IPV4_ADDR_RANGE) ? 4 : 16;
-
- from = ts->get_from_address(ts);
- to = ts->get_to_address(ts);
+ host_t *net_host;
+ chunk_t net_chunk;
- *mask = (size * 8);
- /* go trough all bits of the addresses, beginning in the front.
- * as long as they are equal, the subnet gets larger
- */
- for (byte = 0; byte < size; byte++)
- {
- for (bit = 7; bit >= 0; bit--)
- {
- if ((1<<bit & from.ptr[byte]) != (1<<bit & to.ptr[byte]))
- {
- *mask = ((7 - bit) + (byte * 8));
- found = TRUE;
- break;
- }
- }
- if (found)
- {
- break;
- }
- }
- memcpy(net, from.ptr, from.len);
- chunk_free(&from);
- chunk_free(&to);
+ ts->to_subnet(ts, &net_host, mask);
+ net_chunk = net_host->get_address(net_host);
+ memcpy(net, net_chunk.ptr, net_chunk.len);
+ net_host->destroy(net_host);
}
/**
@@ -430,6 +413,57 @@ static struct xfrm_selector ts2selector(traffic_selector_t *src,
return sel;
}
+/**
+ * convert a xfrm_selector to a src|dst traffic_selector
+ */
+static traffic_selector_t* selector2ts(struct xfrm_selector *sel, bool src)
+{
+ int family;
+ chunk_t addr;
+ u_int8_t prefixlen;
+ u_int16_t port, port_mask;
+ host_t *host;
+ traffic_selector_t *ts;
+
+ if (src)
+ {
+ addr.ptr = (u_char*)&sel->saddr;
+ prefixlen = sel->prefixlen_s;
+ port = sel->sport;
+ port_mask = sel->sport_mask;
+ }
+ else
+ {
+ addr.ptr = (u_char*)&sel->daddr;
+ prefixlen = sel->prefixlen_d;
+ port = sel->dport;
+ port_mask = sel->dport_mask;
+ }
+
+ /* The Linux 2.6 kernel does not set the selector's family field,
+ * so as a kludge we additionally test the prefix length.
+ */
+ if (sel->family == AF_INET || sel->prefixlen_s == 32)
+ {
+ family = AF_INET;
+ addr.len = 4;
+ }
+ else if (sel->family == AF_INET6 || sel->prefixlen_s == 128)
+ {
+ family = AF_INET6;
+ addr.len = 16;
+ }
+ else
+ {
+ return NULL;
+ }
+ host = host_create_from_chunk(family, addr, 0);
+ port = (port_mask == 0) ? 0 : ntohs(port);
+
+ ts = traffic_selector_create_from_subnet(host, prefixlen, sel->proto, port);
+ host->destroy(host);
+ return ts;
+}
/**
* process a XFRM_MSG_ACQUIRE from kernel
@@ -438,18 +472,31 @@ static void process_acquire(private_kernel_netlink_ipsec_t *this, struct nlmsghd
{
u_int32_t reqid = 0;
int proto = 0;
+ traffic_selector_t *src_ts, *dst_ts;
+ struct xfrm_user_acquire *acquire;
+ struct rtattr *rta;
+ size_t rtasize;
job_t *job;
- struct rtattr *rtattr = XFRM_RTA(hdr, struct xfrm_user_acquire);
- size_t rtsize = XFRM_PAYLOAD(hdr, struct xfrm_user_tmpl);
- if (RTA_OK(rtattr, rtsize))
+ acquire = (struct xfrm_user_acquire*)NLMSG_DATA(hdr);
+ rta = XFRM_RTA(hdr, struct xfrm_user_acquire);
+ rtasize = XFRM_PAYLOAD(hdr, struct xfrm_user_acquire);
+
+ DBG2(DBG_KNL, "received a XFRM_MSG_ACQUIRE");
+
+ while (RTA_OK(rta, rtasize))
{
- if (rtattr->rta_type == XFRMA_TMPL)
+ DBG2(DBG_KNL, " %N", xfrm_attr_type_names, rta->rta_type);
+
+ if (rta->rta_type == XFRMA_TMPL)
{
- struct xfrm_user_tmpl* tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rtattr);
+ struct xfrm_user_tmpl* tmpl;
+
+ tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rta);
reqid = tmpl->reqid;
proto = tmpl->id.proto;
}
+ rta = RTA_NEXT(rta, rtasize);
}
switch (proto)
{
@@ -461,14 +508,11 @@ static void process_acquire(private_kernel_netlink_ipsec_t *this, struct nlmsghd
/* acquire for AH/ESP only, not for IPCOMP */
return;
}
- if (reqid == 0)
- {
- DBG1(DBG_KNL, "received a XFRM_MSG_ACQUIRE, but no reqid found");
- return;
- }
- DBG2(DBG_KNL, "received a XFRM_MSG_ACQUIRE");
- DBG1(DBG_KNL, "creating acquire job for CHILD_SA with reqid {%d}", reqid);
- job = (job_t*)acquire_job_create(reqid);
+ src_ts = selector2ts(&acquire->sel, TRUE);
+ dst_ts = selector2ts(&acquire->sel, FALSE);
+ DBG1(DBG_KNL, "creating acquire job for policy %R === %R with reqid {%u}",
+ src_ts, dst_ts, reqid);
+ job = (job_t*)acquire_job_create(reqid, src_ts, dst_ts);
charon->processor->queue_job(charon->processor, job);
}
@@ -491,7 +535,7 @@ static void process_expire(private_kernel_netlink_ipsec_t *this, struct nlmsghdr
if (protocol != PROTO_ESP && protocol != PROTO_AH)
{
- DBG2(DBG_KNL, "ignoring XFRM_MSG_EXPIRE for SA with SPI %.8x and reqid {%d} "
+ DBG2(DBG_KNL, "ignoring XFRM_MSG_EXPIRE for SA with SPI %.8x and reqid {%u} "
"which is not a CHILD_SA", ntohl(spi), reqid);
return;
}
@@ -511,6 +555,86 @@ static void process_expire(private_kernel_netlink_ipsec_t *this, struct nlmsghdr
}
/**
+ * process a XFRM_MSG_MIGRATE from kernel
+ */
+static void process_migrate(private_kernel_netlink_ipsec_t *this, struct nlmsghdr *hdr)
+{
+ traffic_selector_t *src_ts, *dst_ts;
+ host_t *local = NULL, *remote = NULL;
+ host_t *old_src = NULL, *old_dst = NULL;
+ host_t *new_src = NULL, *new_dst = NULL;
+ struct xfrm_userpolicy_id *policy_id;
+ struct rtattr *rta;
+ size_t rtasize;
+ u_int32_t reqid = 0;
+ policy_dir_t dir;
+ job_t *job;
+
+ policy_id = (struct xfrm_userpolicy_id*)NLMSG_DATA(hdr);
+ rta = XFRM_RTA(hdr, struct xfrm_userpolicy_id);
+ rtasize = XFRM_PAYLOAD(hdr, struct xfrm_userpolicy_id);
+
+ DBG2(DBG_KNL, "received a XFRM_MSG_MIGRATE");
+
+ src_ts = selector2ts(&policy_id->sel, TRUE);
+ dst_ts = selector2ts(&policy_id->sel, FALSE);
+ dir = (policy_dir_t)policy_id->dir;
+
+ DBG2(DBG_KNL, " policy: %R === %R %N", src_ts, dst_ts, policy_dir_names);
+
+ while (RTA_OK(rta, rtasize))
+ {
+ DBG2(DBG_KNL, " %N", xfrm_attr_type_names, rta->rta_type);
+ if (rta->rta_type == XFRMA_KMADDRESS)
+ {
+ struct xfrm_user_kmaddress *kmaddress;
+
+ kmaddress = (struct xfrm_user_kmaddress*)RTA_DATA(rta);
+ local = xfrm2host(kmaddress->family, &kmaddress->local, 0);
+ remote = xfrm2host(kmaddress->family, &kmaddress->remote, 0);
+ DBG2(DBG_KNL, " kmaddress: %H...%H", local, remote);
+ }
+ else if (rta->rta_type == XFRMA_MIGRATE)
+ {
+ struct xfrm_user_migrate *migrate;
+ protocol_id_t proto;
+
+ migrate = (struct xfrm_user_migrate*)RTA_DATA(rta);
+ old_src = xfrm2host(migrate->old_family, &migrate->old_saddr, 0);
+ old_dst = xfrm2host(migrate->old_family, &migrate->old_daddr, 0);
+ new_src = xfrm2host(migrate->new_family, &migrate->new_saddr, 0);
+ new_dst = xfrm2host(migrate->new_family, &migrate->new_daddr, 0);
+ proto = proto_kernel2ike(migrate->proto);
+ reqid = migrate->reqid;
+ DBG2(DBG_KNL, " migrate %N %H...%H to %H...%H, reqid {%u}",
+ protocol_id_names, proto, old_src, old_dst,
+ new_src, new_dst, reqid);
+ DESTROY_IF(old_src);
+ DESTROY_IF(old_dst);
+ DESTROY_IF(new_src);
+ DESTROY_IF(new_dst);
+ }
+ rta = RTA_NEXT(rta, rtasize);
+ }
+
+ if (src_ts && dst_ts && local && remote)
+ {
+ DBG1(DBG_KNL, "creating migrate job for policy %R === %R %N with reqid {%u}",
+ src_ts, dst_ts, policy_dir_names, dir, reqid, local);
+ job = (job_t*)migrate_job_create(reqid, src_ts, dst_ts, dir,
+ local, remote);
+ charon->processor->queue_job(charon->processor, job);
+ }
+ else
+ {
+ DESTROY_IF(src_ts);
+ DESTROY_IF(dst_ts);
+ DESTROY_IF(local);
+ DESTROY_IF(remote);
+ }
+}
+
+/**
* process a XFRM_MSG_MAPPING from kernel
*/
static void process_mapping(private_kernel_netlink_ipsec_t *this,
@@ -534,7 +658,7 @@ static void process_mapping(private_kernel_netlink_ipsec_t *this,
if (host)
{
DBG1(DBG_KNL, "NAT mappings of ESP CHILD_SA with SPI %.8x and "
- "reqid {%d} changed, queueing update job", ntohl(spi), reqid);
+ "reqid {%u} changed, queuing update job", ntohl(spi), reqid);
job = (job_t*)update_sa_job_create(reqid, host);
charon->processor->queue_job(charon->processor, job);
}
@@ -589,6 +713,9 @@ static job_requeue_t receive_events(private_kernel_netlink_ipsec_t *this)
case XFRM_MSG_EXPIRE:
process_expire(this, hdr);
break;
+ case XFRM_MSG_MIGRATE:
+ process_migrate(this, hdr);
+ break;
case XFRM_MSG_MAPPING:
process_mapping(this, hdr);
break;
@@ -601,71 +728,13 @@ static job_requeue_t receive_events(private_kernel_netlink_ipsec_t *this)
}
/**
- * Tries to find an ip address of a local interface that is included in the
- * supplied traffic selector.
- */
-static status_t get_address_by_ts(private_kernel_netlink_ipsec_t *this,
- traffic_selector_t *ts, host_t **ip)
-{
- enumerator_t *addrs;
- host_t *host;
- int family;
- bool found = FALSE;
-
- DBG2(DBG_KNL, "getting a local address in traffic selector %R", ts);
-
- /* if we have a family which includes localhost, we do not
- * search for an IP, we use the default */
- family = ts->get_type(ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6;
-
- if (family == AF_INET)
- {
- host = host_create_from_string("127.0.0.1", 0);
- }
- else
- {
- host = host_create_from_string("::1", 0);
- }
-
- if (ts->includes(ts, host))
- {
- *ip = host_create_any(family);
- host->destroy(host);
- DBG2(DBG_KNL, "using host %H", *ip);
- return SUCCESS;
- }
- host->destroy(host);
-
- addrs = charon->kernel_interface->create_address_enumerator(
- charon->kernel_interface, TRUE, TRUE);
- while (addrs->enumerate(addrs, (void**)&host))
- {
- if (ts->includes(ts, host))
- {
- found = TRUE;
- *ip = host->clone(host);
- break;
- }
- }
- addrs->destroy(addrs);
-
- if (!found)
- {
- DBG1(DBG_KNL, "no local address found in traffic selector %R", ts);
- return FAILED;
- }
- DBG2(DBG_KNL, "using host %H", *ip);
- return SUCCESS;
-}
-
-/**
* Get an SPI for a specific protocol from the kernel.
*/
static status_t get_spi_internal(private_kernel_netlink_ipsec_t *this,
host_t *src, host_t *dst, u_int8_t proto, u_int32_t min, u_int32_t max,
u_int32_t reqid, u_int32_t *spi)
{
- unsigned char request[NETLINK_BUFFER_SIZE];
+ netlink_buf_t request;
struct nlmsghdr *hdr, *out;
struct xfrm_userspi_info *userspi;
u_int32_t received_spi = 0;
@@ -737,16 +806,16 @@ static status_t get_spi(private_kernel_netlink_ipsec_t *this,
protocol_id_t protocol, u_int32_t reqid,
u_int32_t *spi)
{
- DBG2(DBG_KNL, "getting SPI for reqid {%d}", reqid);
+ DBG2(DBG_KNL, "getting SPI for reqid {%u}", reqid);
if (get_spi_internal(this, src, dst, proto_ike2kernel(protocol),
0xc0000000, 0xcFFFFFFF, reqid, spi) != SUCCESS)
{
- DBG1(DBG_KNL, "unable to get SPI for reqid {%d}", reqid);
+ DBG1(DBG_KNL, "unable to get SPI for reqid {%u}", reqid);
return FAILED;
}
- DBG2(DBG_KNL, "got SPI %.8x for reqid {%d}", ntohl(*spi), reqid);
+ DBG2(DBG_KNL, "got SPI %.8x for reqid {%u}", ntohl(*spi), reqid);
return SUCCESS;
}
@@ -760,18 +829,18 @@ static status_t get_cpi(private_kernel_netlink_ipsec_t *this,
{
u_int32_t received_spi = 0;
- DBG2(DBG_KNL, "getting CPI for reqid {%d}", reqid);
+ DBG2(DBG_KNL, "getting CPI for reqid {%u}", reqid);
if (get_spi_internal(this, src, dst,
IPPROTO_COMP, 0x100, 0xEFFF, reqid, &received_spi) != SUCCESS)
{
- DBG1(DBG_KNL, "unable to get CPI for reqid {%d}", reqid);
+ DBG1(DBG_KNL, "unable to get CPI for reqid {%u}", reqid);
return FAILED;
}
*cpi = htons((u_int16_t)ntohl(received_spi));
- DBG2(DBG_KNL, "got CPI %.4x for reqid {%d}", ntohs(*cpi), reqid);
+ DBG2(DBG_KNL, "got CPI %.4x for reqid {%u}", ntohs(*cpi), reqid);
return SUCCESS;
}
@@ -783,26 +852,35 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
host_t *src, host_t *dst, u_int32_t spi,
protocol_id_t protocol, u_int32_t reqid,
u_int64_t expire_soft, u_int64_t expire_hard,
- u_int16_t enc_alg, u_int16_t enc_size,
- u_int16_t int_alg, u_int16_t int_size,
- prf_plus_t *prf_plus, ipsec_mode_t mode,
- u_int16_t ipcomp, bool encap,
- bool replace)
+ u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key,
+ ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool encap, bool inbound)
{
- unsigned char request[NETLINK_BUFFER_SIZE];
+ netlink_buf_t request;
char *alg_name;
- /* additional 4 octets KEYMAT required for AES-GCM as of RFC4106 8.1. */
- u_int16_t add_keymat = 32;
struct nlmsghdr *hdr;
struct xfrm_usersa_info *sa;
+ u_int16_t icv_size = 64;
+
+ /* if IPComp is used, we install an additional IPComp SA. if the cpi is 0
+ * we are in the recursive call below */
+ if (ipcomp != IPCOMP_NONE && cpi != 0)
+ {
+ add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, 0, 0,
+ ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty,
+ mode, ipcomp, 0, FALSE, inbound);
+ ipcomp = IPCOMP_NONE;
+ }
memset(&request, 0, sizeof(request));
- DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%d}", ntohl(spi), reqid);
-
+ DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}",
+ ntohl(spi), reqid);
+
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
- hdr->nlmsg_type = replace ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
+ hdr->nlmsg_type = inbound ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
sa = (struct xfrm_usersa_info*)NLMSG_DATA(hdr);
@@ -836,19 +914,19 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
case ENCR_UNDEFINED:
/* no encryption */
break;
- case ENCR_AES_CCM_ICV8:
- case ENCR_AES_CCM_ICV12:
case ENCR_AES_CCM_ICV16:
- /* AES-CCM needs only 3 additional octets KEYMAT as of RFC 4309 7.1. */
- add_keymat = 24;
- /* fall-through */
- case ENCR_AES_GCM_ICV8:
- case ENCR_AES_GCM_ICV12:
case ENCR_AES_GCM_ICV16:
+ icv_size += 32;
+ /* FALL */
+ case ENCR_AES_CCM_ICV12:
+ case ENCR_AES_GCM_ICV12:
+ icv_size += 32;
+ /* FALL */
+ case ENCR_AES_CCM_ICV8:
+ case ENCR_AES_GCM_ICV8:
{
- u_int16_t icv_size = 0;
rthdr->rta_type = XFRMA_ALG_AEAD;
- alg_name = lookup_algorithm(encryption_algs, enc_alg, &icv_size);
+ alg_name = lookup_algorithm(encryption_algs, enc_alg);
if (alg_name == NULL)
{
DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
@@ -856,12 +934,9 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
return FAILED;
}
DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
- encryption_algorithm_names, enc_alg, enc_size);
+ encryption_algorithm_names, enc_alg, enc_key.len * 8);
- /* additional KEYMAT required */
- enc_size += add_keymat;
-
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_aead) + enc_size / 8);
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_aead) + enc_key.len);
hdr->nlmsg_len += rthdr->rta_len;
if (hdr->nlmsg_len > sizeof(request))
{
@@ -869,10 +944,10 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
}
struct xfrm_algo_aead* algo = (struct xfrm_algo_aead*)RTA_DATA(rthdr);
- algo->alg_key_len = enc_size;
+ algo->alg_key_len = enc_key.len * 8;
algo->alg_icv_len = icv_size;
strcpy(algo->alg_name, alg_name);
- prf_plus->get_bytes(prf_plus, enc_size / 8, algo->alg_key);
+ memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
rthdr = XFRM_RTA_NEXT(rthdr);
break;
@@ -880,7 +955,7 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
default:
{
rthdr->rta_type = XFRMA_ALG_CRYPT;
- alg_name = lookup_algorithm(encryption_algs, enc_alg, &enc_size);
+ alg_name = lookup_algorithm(encryption_algs, enc_alg);
if (alg_name == NULL)
{
DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
@@ -888,9 +963,9 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
return FAILED;
}
DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
- encryption_algorithm_names, enc_alg, enc_size);
+ encryption_algorithm_names, enc_alg, enc_key.len * 8);
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + enc_size / 8);
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + enc_key.len);
hdr->nlmsg_len += rthdr->rta_len;
if (hdr->nlmsg_len > sizeof(request))
{
@@ -898,9 +973,9 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
}
struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr);
- algo->alg_key_len = enc_size;
+ algo->alg_key_len = enc_key.len * 8;
strcpy(algo->alg_name, alg_name);
- prf_plus->get_bytes(prf_plus, enc_size / 8, algo->alg_key);
+ memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
rthdr = XFRM_RTA_NEXT(rthdr);
break;
@@ -910,7 +985,7 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
if (int_alg != AUTH_UNDEFINED)
{
rthdr->rta_type = XFRMA_ALG_AUTH;
- alg_name = lookup_algorithm(integrity_algs, int_alg, &int_size);
+ alg_name = lookup_algorithm(integrity_algs, int_alg);
if (alg_name == NULL)
{
DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
@@ -918,9 +993,9 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
return FAILED;
}
DBG2(DBG_KNL, " using integrity algorithm %N with key size %d",
- integrity_algorithm_names, int_alg, int_size);
+ integrity_algorithm_names, int_alg, int_key.len * 8);
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + int_size / 8);
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + int_key.len);
hdr->nlmsg_len += rthdr->rta_len;
if (hdr->nlmsg_len > sizeof(request))
{
@@ -928,9 +1003,9 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
}
struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr);
- algo->alg_key_len = int_size;
+ algo->alg_key_len = int_key.len * 8;
strcpy(algo->alg_name, alg_name);
- prf_plus->get_bytes(prf_plus, int_size / 8, algo->alg_key);
+ memcpy(algo->alg_key, int_key.ptr, int_key.len);
rthdr = XFRM_RTA_NEXT(rthdr);
}
@@ -938,7 +1013,7 @@ static status_t add_sa(private_kernel_netlink_ipsec_t *this,
if (ipcomp != IPCOMP_NONE)
{
rthdr->rta_type = XFRMA_ALG_COMP;
- alg_name = lookup_algorithm(compression_algs, ipcomp, NULL);
+ alg_name = lookup_algorithm(compression_algs, ipcomp);
if (alg_name == NULL)
{
DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
@@ -1005,7 +1080,7 @@ static status_t get_replay_state(private_kernel_netlink_ipsec_t *this,
u_int32_t spi, protocol_id_t protocol, host_t *dst,
struct xfrm_replay_state *replay)
{
- unsigned char request[NETLINK_BUFFER_SIZE];
+ netlink_buf_t request;
struct nlmsghdr *hdr, *out = NULL;
struct xfrm_aevent_id *out_aevent = NULL, *aevent_id;
size_t len;
@@ -1020,7 +1095,7 @@ static status_t get_replay_state(private_kernel_netlink_ipsec_t *this,
hdr->nlmsg_flags = NLM_F_REQUEST;
hdr->nlmsg_type = XFRM_MSG_GETAE;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id));
-
+
aevent_id = (struct xfrm_aevent_id*)NLMSG_DATA(hdr);
aevent_id->flags = XFRM_AE_RVAL;
@@ -1070,9 +1145,10 @@ static status_t get_replay_state(private_kernel_netlink_ipsec_t *this,
rtasize = XFRM_PAYLOAD(out, struct xfrm_aevent_id);
while(RTA_OK(rta, rtasize))
{
- if (rta->rta_type == XFRMA_REPLAY_VAL)
+ if (rta->rta_type == XFRMA_REPLAY_VAL &&
+ RTA_PAYLOAD(rta) == sizeof(struct xfrm_replay_state))
{
- memcpy(replay, RTA_DATA(rta), rta->rta_len);
+ memcpy(replay, RTA_DATA(rta), RTA_PAYLOAD(rta));
free(out);
return SUCCESS;
}
@@ -1086,14 +1162,56 @@ static status_t get_replay_state(private_kernel_netlink_ipsec_t *this,
}
/**
+ * Implementation of kernel_interface_t.del_sa.
+ */
+static status_t del_sa(private_kernel_netlink_ipsec_t *this, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi)
+{
+ netlink_buf_t request;
+ struct nlmsghdr *hdr;
+ struct xfrm_usersa_id *sa_id;
+
+ /* if IPComp was used, we first delete the additional IPComp SA */
+ if (cpi)
+ {
+ del_sa(this, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0);
+ }
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi));
+
+ hdr = (struct nlmsghdr*)request;
+ hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ hdr->nlmsg_type = XFRM_MSG_DELSA;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
+
+ sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
+ host2xfrm(dst, &sa_id->daddr);
+ sa_id->spi = spi;
+ sa_id->proto = proto_ike2kernel(protocol);
+ sa_id->family = dst->get_family(dst);
+
+ if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi));
+ return SUCCESS;
+}
+
+/**
* Implementation of kernel_interface_t.update_sa.
*/
static status_t update_sa(private_kernel_netlink_ipsec_t *this,
- u_int32_t spi, protocol_id_t protocol,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
host_t *src, host_t *dst,
- host_t *new_src, host_t *new_dst, bool encap)
+ host_t *new_src, host_t *new_dst,
+ bool old_encap, bool new_encap)
{
- unsigned char request[NETLINK_BUFFER_SIZE], *pos;
+ netlink_buf_t request;
+ u_char *pos;
struct nlmsghdr *hdr, *out = NULL;
struct xfrm_usersa_id *sa_id;
struct xfrm_usersa_info *out_sa = NULL, *sa;
@@ -1101,19 +1219,26 @@ static status_t update_sa(private_kernel_netlink_ipsec_t *this,
struct rtattr *rta;
size_t rtasize;
struct xfrm_encap_tmpl* tmpl = NULL;
- bool got_replay_state;
+ bool got_replay_state = FALSE;
struct xfrm_replay_state replay;
+ /* if IPComp is used, we first update the IPComp SA */
+ if (cpi)
+ {
+ update_sa(this, htonl(ntohs(cpi)), IPPROTO_COMP, 0,
+ src, dst, new_src, new_dst, FALSE, FALSE);
+ }
+
memset(&request, 0, sizeof(request));
DBG2(DBG_KNL, "querying SAD entry with SPI %.8x for update", ntohl(spi));
-
+
/* query the existing SA first */
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST;
hdr->nlmsg_type = XFRM_MSG_GETSA;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
-
+
sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
host2xfrm(dst, &sa_id->daddr);
sa_id->spi = spi;
@@ -1156,11 +1281,13 @@ static status_t update_sa(private_kernel_netlink_ipsec_t *this,
}
/* try to get the replay state */
- got_replay_state = (get_replay_state(
- this, spi, protocol, dst, &replay) == SUCCESS);
+ if (get_replay_state(this, spi, protocol, dst, &replay) == SUCCESS)
+ {
+ got_replay_state = TRUE;
+ }
- /* delete the old SA */
- if (this->public.interface.del_sa(&this->public.interface, dst, spi, protocol) != SUCCESS)
+ /* delete the old SA (without affecting the IPComp SA) */
+ if (del_sa(this, dst, spi, protocol, 0) != SUCCESS)
{
DBG1(DBG_KNL, "unable to delete old SAD entry with SPI %.8x", ntohl(spi));
free(out);
@@ -1169,7 +1296,6 @@ static status_t update_sa(private_kernel_netlink_ipsec_t *this,
DBG2(DBG_KNL, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H",
ntohl(spi), src, dst, new_src, new_dst);
-
/* copy over the SA from out to request */
hdr = (struct nlmsghdr*)request;
memcpy(hdr, out, min(out->nlmsg_len, sizeof(request)));
@@ -1194,7 +1320,7 @@ static status_t update_sa(private_kernel_netlink_ipsec_t *this,
while(RTA_OK(rta, rtasize))
{
/* copy all attributes, but not XFRMA_ENCAP if we are disabling it */
- if (rta->rta_type != XFRMA_ENCAP || encap)
+ if (rta->rta_type != XFRMA_ENCAP || new_encap)
{
if (rta->rta_type == XFRMA_ENCAP)
{ /* update encap tmpl */
@@ -1210,7 +1336,7 @@ static status_t update_sa(private_kernel_netlink_ipsec_t *this,
}
rta = (struct rtattr*)pos;
- if (tmpl == NULL && encap)
+ if (tmpl == NULL && new_encap)
{ /* add tmpl if we are enabling it */
rta->rta_type = XFRMA_ENCAP;
rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl));
@@ -1257,122 +1383,21 @@ static status_t update_sa(private_kernel_netlink_ipsec_t *this,
}
/**
- * Implementation of kernel_interface_t.query_sa.
- */
-static status_t query_sa(private_kernel_netlink_ipsec_t *this, host_t *dst,
- u_int32_t spi, protocol_id_t protocol,
- u_int32_t *use_time)
-{
- unsigned char request[NETLINK_BUFFER_SIZE];
- struct nlmsghdr *out = NULL, *hdr;
- struct xfrm_usersa_id *sa_id;
- struct xfrm_usersa_info *sa = NULL;
- size_t len;
-
- DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
- memset(&request, 0, sizeof(request));
-
- hdr = (struct nlmsghdr*)request;
- hdr->nlmsg_flags = NLM_F_REQUEST;
- hdr->nlmsg_type = XFRM_MSG_GETSA;
- hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
-
- sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
- host2xfrm(dst, &sa_id->daddr);
- sa_id->spi = spi;
- sa_id->proto = proto_ike2kernel(protocol);
- sa_id->family = dst->get_family(dst);
-
- if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
- {
- hdr = out;
- while (NLMSG_OK(hdr, len))
- {
- switch (hdr->nlmsg_type)
- {
- case XFRM_MSG_NEWSA:
- {
- sa = NLMSG_DATA(hdr);
- break;
- }
- case NLMSG_ERROR:
- {
- struct nlmsgerr *err = NLMSG_DATA(hdr);
- DBG1(DBG_KNL, "querying SAD entry failed: %s (%d)",
- strerror(-err->error), -err->error);
- break;
- }
- default:
- hdr = NLMSG_NEXT(hdr, len);
- continue;
- case NLMSG_DONE:
- break;
- }
- break;
- }
- }
-
- if (sa == NULL)
- {
- DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi));
- free(out);
- return FAILED;
- }
-
- *use_time = sa->curlft.use_time;
- free (out);
- return SUCCESS;
-}
-
-/**
- * Implementation of kernel_interface_t.del_sa.
- */
-static status_t del_sa(private_kernel_netlink_ipsec_t *this, host_t *dst,
- u_int32_t spi, protocol_id_t protocol)
-{
- unsigned char request[NETLINK_BUFFER_SIZE];
- struct nlmsghdr *hdr;
- struct xfrm_usersa_id *sa_id;
-
- memset(&request, 0, sizeof(request));
-
- DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi));
-
- hdr = (struct nlmsghdr*)request;
- hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
- hdr->nlmsg_type = XFRM_MSG_DELSA;
- hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
-
- sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
- host2xfrm(dst, &sa_id->daddr);
- sa_id->spi = spi;
- sa_id->proto = proto_ike2kernel(protocol);
- sa_id->family = dst->get_family(dst);
-
- if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
- {
- DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi));
- return FAILED;
- }
- DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi));
- return SUCCESS;
-}
-
-/**
* Implementation of kernel_interface_t.add_policy.
*/
static status_t add_policy(private_kernel_netlink_ipsec_t *this,
host_t *src, host_t *dst,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
- policy_dir_t direction, protocol_id_t protocol,
- u_int32_t reqid, bool high_prio, ipsec_mode_t mode,
- u_int16_t ipcomp)
+ policy_dir_t direction, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid,
+ ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool routed)
{
iterator_t *iterator;
policy_entry_t *current, *policy;
bool found = FALSE;
- unsigned char request[NETLINK_BUFFER_SIZE];
+ netlink_buf_t request;
struct xfrm_userpolicy_info *policy_info;
struct nlmsghdr *hdr;
@@ -1383,7 +1408,7 @@ static status_t add_policy(private_kernel_netlink_ipsec_t *this,
policy->direction = direction;
/* find the policy, which matches EXACTLY */
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
iterator = this->policies->create_iterator(this->policies, TRUE);
while (iterator->iterate(iterator, (void**)&current))
{
@@ -1421,13 +1446,13 @@ static status_t add_policy(private_kernel_netlink_ipsec_t *this,
policy_info->sel = policy->sel;
policy_info->dir = policy->direction;
/* calculate priority based on source selector size, small size = high prio */
- policy_info->priority = high_prio ? PRIO_HIGH : PRIO_LOW;
+ policy_info->priority = routed ? PRIO_LOW : PRIO_HIGH;
policy_info->priority -= policy->sel.prefixlen_s * 10;
policy_info->priority -= policy->sel.proto ? 2 : 0;
policy_info->priority -= policy->sel.sport_mask ? 1 : 0;
policy_info->action = XFRM_POLICY_ALLOW;
policy_info->share = XFRM_SHARE_ANY;
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
/* policies don't expire */
policy_info->lft.soft_byte_limit = XFRM_INF;
@@ -1503,7 +1528,8 @@ static status_t add_policy(private_kernel_netlink_ipsec_t *this,
{
route_entry_t *route = malloc_thing(route_entry_t);
- if (get_address_by_ts(this, dst_ts, &route->src_ip) == SUCCESS)
+ if (charon->kernel_interface->get_address_by_ts(charon->kernel_interface,
+ dst_ts, &route->src_ip) == SUCCESS)
{
/* get the nexthop to src (src as we are in POLICY_FWD).*/
route->gateway = charon->kernel_interface->get_nexthop(
@@ -1514,22 +1540,30 @@ static status_t add_policy(private_kernel_netlink_ipsec_t *this,
memcpy(route->dst_net.ptr, &policy->sel.saddr, route->dst_net.len);
route->prefixlen = policy->sel.prefixlen_s;
- switch (charon->kernel_interface->add_route(charon->kernel_interface,
- route->dst_net, route->prefixlen, route->gateway,
- route->src_ip, route->if_name))
+ if (route->if_name)
+ {
+ switch (charon->kernel_interface->add_route(
+ charon->kernel_interface, route->dst_net,
+ route->prefixlen, route->gateway,
+ route->src_ip, route->if_name))
+ {
+ default:
+ DBG1(DBG_KNL, "unable to install source route for %H",
+ route->src_ip);
+ /* FALL */
+ case ALREADY_DONE:
+ /* route exists, do not uninstall */
+ route_entry_destroy(route);
+ break;
+ case SUCCESS:
+ /* cache the installed route */
+ policy->route = route;
+ break;
+ }
+ }
+ else
{
- default:
- DBG1(DBG_KNL, "unable to install source route for %H",
- route->src_ip);
- /* FALL */
- case ALREADY_DONE:
- /* route exists, do not uninstall */
- route_entry_destroy(route);
- break;
- case SUCCESS:
- /* cache the installed route */
- policy->route = route;
- break;
+ route_entry_destroy(route);
}
}
else
@@ -1537,7 +1571,6 @@ static status_t add_policy(private_kernel_netlink_ipsec_t *this,
free(route);
}
}
-
return SUCCESS;
}
@@ -1549,7 +1582,7 @@ static status_t query_policy(private_kernel_netlink_ipsec_t *this,
traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t *use_time)
{
- unsigned char request[NETLINK_BUFFER_SIZE];
+ netlink_buf_t request;
struct nlmsghdr *out = NULL, *hdr;
struct xfrm_userpolicy_id *policy_id;
struct xfrm_userpolicy_info *policy = NULL;
@@ -1617,14 +1650,14 @@ static status_t query_policy(private_kernel_netlink_ipsec_t *this,
static status_t del_policy(private_kernel_netlink_ipsec_t *this,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
- policy_dir_t direction)
+ policy_dir_t direction, bool unrouted)
{
policy_entry_t *current, policy, *to_delete = NULL;
route_entry_t *route;
- unsigned char request[NETLINK_BUFFER_SIZE];
+ netlink_buf_t request;
struct nlmsghdr *hdr;
struct xfrm_userpolicy_id *policy_id;
- iterator_t *iterator;
+ enumerator_t *enumerator;
DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts,
policy_dir_names, direction);
@@ -1635,10 +1668,11 @@ static status_t del_policy(private_kernel_netlink_ipsec_t *this,
policy.direction = direction;
/* find the policy */
- iterator = this->policies->create_iterator_locked(this->policies, &this->mutex);
- while (iterator->iterate(iterator, (void**)&current))
+ this->mutex->lock(this->mutex);
+ enumerator = this->policies->create_enumerator(this->policies);
+ while (enumerator->enumerate(enumerator, &current))
{
- if (memcmp(&current->sel, &policy.sel, sizeof(struct xfrm_selector)) == 0 &&
+ if (memeq(&current->sel, &policy.sel, sizeof(struct xfrm_selector)) &&
policy.direction == current->direction)
{
to_delete = current;
@@ -1646,15 +1680,17 @@ static status_t del_policy(private_kernel_netlink_ipsec_t *this,
{
/* is used by more SAs, keep in kernel */
DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
- iterator->destroy(iterator);
+ this->mutex->unlock(this->mutex);
+ enumerator->destroy(enumerator);
return SUCCESS;
}
/* remove if last reference */
- iterator->remove(iterator);
+ this->policies->remove_at(this->policies, enumerator);
break;
}
}
- iterator->destroy(iterator);
+ this->mutex->unlock(this->mutex);
+ enumerator->destroy(enumerator);
if (!to_delete)
{
DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts,
@@ -1707,9 +1743,75 @@ static void destroy(private_kernel_netlink_ipsec_t *this)
close(this->socket_xfrm_events);
this->socket_xfrm->destroy(this->socket_xfrm);
this->policies->destroy(this->policies);
+ this->mutex->destroy(this->mutex);
free(this);
}
+/**
+ * Add bypass policies for IKE on the sockets used by charon
+ */
+static bool add_bypass_policies()
+{
+ int fd, family, port;
+ enumerator_t *sockets;
+ bool status = TRUE;
+
+ /* we open an AF_KEY socket to autoload the af_key module. Otherwise
+ * setsockopt(IPSEC_POLICY) won't work. */
+ fd = socket(AF_KEY, SOCK_RAW, PF_KEY_V2);
+ if (fd == 0)
+ {
+ DBG1(DBG_KNL, "could not open AF_KEY socket");
+ return FALSE;
+ }
+ close(fd);
+
+ sockets = charon->socket->create_enumerator(charon->socket);
+ while (sockets->enumerate(sockets, &fd, &family, &port))
+ {
+ struct sadb_x_policy policy;
+ u_int sol, ipsec_policy;
+
+ switch (family)
+ {
+ case AF_INET:
+ sol = SOL_IP;
+ ipsec_policy = IP_IPSEC_POLICY;
+ break;
+ case AF_INET6:
+ sol = SOL_IPV6;
+ ipsec_policy = IPV6_IPSEC_POLICY;
+ break;
+ default:
+ continue;
+ }
+
+ memset(&policy, 0, sizeof(policy));
+ policy.sadb_x_policy_len = sizeof(policy) / sizeof(u_int64_t);
+ policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+ policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS;
+
+ policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
+ if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
+ {
+ DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
+ strerror(errno));
+ status = FALSE;
+ break;
+ }
+ policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
+ if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
+ {
+ DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
+ strerror(errno));
+ status = FALSE;
+ break;
+ }
+ }
+ sockets->destroy(sockets);
+ return status;
+}
+
/*
* Described in header.
*/
@@ -1721,33 +1823,39 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
/* public functions */
this->public.interface.get_spi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
- this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,u_int16_t,u_int16_t,u_int16_t,prf_plus_t*,ipsec_mode_t,u_int16_t,bool,bool))add_sa;
- this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_t*,host_t*,bool))update_sa;
- this->public.interface.query_sa = (status_t(*)(kernel_ipsec_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t*))query_sa;
- this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
- this->public.interface.add_policy = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool,ipsec_mode_t,u_int16_t))add_policy;
+ this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool))add_sa;
+ this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,u_int16_t,host_t*,host_t*,host_t*,host_t*,bool,bool))update_sa;
+ this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,u_int32_t,protocol_id_t,u_int16_t))del_sa;
+ this->public.interface.add_policy = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t,protocol_id_t,u_int32_t,ipsec_mode_t,u_int16_t,u_int16_t,bool))add_policy;
this->public.interface.query_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
- this->public.interface.del_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t))del_policy;
+ this->public.interface.del_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,bool))del_policy;
this->public.interface.destroy = (void(*)(kernel_ipsec_t*)) destroy;
/* private members */
this->policies = linked_list_create();
- pthread_mutex_init(&this->mutex, NULL);
+ this->mutex = mutex_create(MUTEX_DEFAULT);
this->install_routes = lib->settings->get_bool(lib->settings,
"charon.install_routes", TRUE);
+ /* add bypass policies on the sockets used by charon */
+ if (!add_bypass_policies())
+ {
+ charon->kill(charon, "unable to add bypass policies on sockets");
+ }
+
this->socket_xfrm = netlink_socket_create(NETLINK_XFRM);
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
- /* create and bind XFRM socket for ACQUIRE & EXPIRE */
+ /* create and bind XFRM socket for ACQUIRE, EXPIRE, MIGRATE & MAPPING */
this->socket_xfrm_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_XFRM);
if (this->socket_xfrm_events <= 0)
{
charon->kill(charon, "unable to create XFRM event socket");
}
- addr.nl_groups = XFRMNLGRP(ACQUIRE) | XFRMNLGRP(EXPIRE) | XFRMNLGRP(MAPPING);
+ addr.nl_groups = XFRMNLGRP(ACQUIRE) | XFRMNLGRP(EXPIRE) |
+ XFRMNLGRP(MIGRATE) | XFRMNLGRP(MAPPING);
if (bind(this->socket_xfrm_events, (struct sockaddr*)&addr, sizeof(addr)))
{
charon->kill(charon, "unable to bind XFRM event socket");
diff --git a/src/charon/plugins/kernel_netlink/kernel_netlink_net.c b/src/charon/plugins/kernel_netlink/kernel_netlink_net.c
index d8bba9412..69a781c14 100644
--- a/src/charon/plugins/kernel_netlink/kernel_netlink_net.c
+++ b/src/charon/plugins/kernel_netlink/kernel_netlink_net.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: kernel_netlink_net.c 4391 2008-10-09 05:44:00Z andreas $
+ * $Id: kernel_netlink_net.c 4660 2008-11-14 14:23:11Z martin $
*/
#include <sys/socket.h>
@@ -29,6 +29,7 @@
#include "kernel_netlink_shared.h"
#include <daemon.h>
+#include <utils/mutex.h>
#include <utils/linked_list.h>
#include <processing/jobs/callback_job.h>
#include <processing/jobs/roam_job.h>
@@ -116,12 +117,12 @@ struct private_kernel_netlink_net_t {
/**
* mutex to lock access to various lists
*/
- pthread_mutex_t mutex;
+ mutex_t *mutex;
/**
* condition variable to signal virtual IP add/removal
*/
- pthread_cond_t cond;
+ condvar_t *condvar;
/**
* Cached list of interfaces and its addresses (iface_entry_t)
@@ -157,7 +158,7 @@ struct private_kernel_netlink_net_t {
* priority of used routing table
*/
int routing_table_prio;
-
+
/**
* whether to react to RTM_NEWROUTE or RTM_DELROUTE events
*/
@@ -206,7 +207,7 @@ static int get_vip_refcount(private_kernel_netlink_net_t *this, host_t* ip)
static void fire_roam_job(private_kernel_netlink_net_t *this, bool address)
{
struct timeval now;
-
+
if (gettimeofday(&now, NULL) == 0)
{
if (timercmp(&now, &this->last_roam, >))
@@ -233,7 +234,7 @@ static void process_link(private_kernel_netlink_net_t *this,
struct ifinfomsg* msg = (struct ifinfomsg*)(NLMSG_DATA(hdr));
struct rtattr *rta = IFLA_RTA(msg);
size_t rtasize = IFLA_PAYLOAD (hdr);
- iterator_t *iterator;
+ enumerator_t *enumerator;
iface_entry_t *current, *entry = NULL;
char *name = NULL;
bool update = FALSE;
@@ -253,6 +254,7 @@ static void process_link(private_kernel_netlink_net_t *this,
name = "(unknown)";
}
+ this->mutex->lock(this->mutex);
switch (hdr->nlmsg_type)
{
case RTM_NEWLINK:
@@ -261,9 +263,8 @@ static void process_link(private_kernel_netlink_net_t *this,
{ /* ignore loopback interfaces */
break;
}
- iterator = this->ifaces->create_iterator_locked(this->ifaces,
- &this->mutex);
- while (iterator->iterate(iterator, (void**)&current))
+ enumerator = this->ifaces->create_enumerator(this->ifaces);
+ while (enumerator->enumerate(enumerator, &current))
{
if (current->ifindex == msg->ifi_index)
{
@@ -271,6 +272,7 @@ static void process_link(private_kernel_netlink_net_t *this,
break;
}
}
+ enumerator->destroy(enumerator);
if (!entry)
{
entry = malloc_thing(iface_entry_t);
@@ -295,14 +297,12 @@ static void process_link(private_kernel_netlink_net_t *this,
}
}
entry->flags = msg->ifi_flags;
- iterator->destroy(iterator);
break;
}
case RTM_DELLINK:
{
- iterator = this->ifaces->create_iterator_locked(this->ifaces,
- &this->mutex);
- while (iterator->iterate(iterator, (void**)&current))
+ enumerator = this->ifaces->create_enumerator(this->ifaces);
+ while (enumerator->enumerate(enumerator, &current))
{
if (current->ifindex == msg->ifi_index)
{
@@ -312,10 +312,11 @@ static void process_link(private_kernel_netlink_net_t *this,
break;
}
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
break;
}
}
+ this->mutex->unlock(this->mutex);
/* send an update to all IKE_SAs */
if (update && event)
@@ -334,7 +335,7 @@ static void process_addr(private_kernel_netlink_net_t *this,
struct rtattr *rta = IFA_RTA(msg);
size_t rtasize = IFA_PAYLOAD (hdr);
host_t *host = NULL;
- iterator_t *ifaces, *addrs;
+ enumerator_t *ifaces, *addrs;
iface_entry_t *iface;
addr_entry_t *addr;
chunk_t local = chunk_empty, address = chunk_empty;
@@ -373,20 +374,21 @@ static void process_addr(private_kernel_netlink_net_t *this,
return;
}
- ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex);
- while (ifaces->iterate(ifaces, (void**)&iface))
+ this->mutex->lock(this->mutex);
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
{
if (iface->ifindex == msg->ifa_index)
{
- addrs = iface->addrs->create_iterator(iface->addrs, TRUE);
- while (addrs->iterate(addrs, (void**)&addr))
+ addrs = iface->addrs->create_enumerator(iface->addrs);
+ while (addrs->enumerate(addrs, &addr))
{
if (host->ip_equals(host, addr->ip))
{
found = TRUE;
if (hdr->nlmsg_type == RTM_DELADDR)
{
- addrs->remove(addrs);
+ iface->addrs->remove_at(iface->addrs, addrs);
if (!addr->virtual)
{
changed = TRUE;
@@ -430,6 +432,7 @@ static void process_addr(private_kernel_netlink_net_t *this,
}
}
ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
host->destroy(host);
/* send an update to all IKE_SAs */
@@ -468,10 +471,12 @@ static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *h
}
if (host)
{
+ this->mutex->lock(this->mutex);
if (!get_vip_refcount(this, host))
{ /* ignore routes added for virtual IPs */
fire_roam_job(this, FALSE);
}
+ this->mutex->unlock(this->mutex);
host->destroy(host);
}
}
@@ -522,12 +527,12 @@ static job_requeue_t receive_events(private_kernel_netlink_net_t *this)
case RTM_NEWADDR:
case RTM_DELADDR:
process_addr(this, hdr, TRUE);
- pthread_cond_broadcast(&this->cond);
+ this->condvar->broadcast(this->condvar);
break;
case RTM_NEWLINK:
case RTM_DELLINK:
process_link(this, hdr, TRUE);
- pthread_cond_broadcast(&this->cond);
+ this->condvar->broadcast(this->condvar);
break;
case RTM_NEWROUTE:
case RTM_DELROUTE:
@@ -558,7 +563,7 @@ typedef struct {
*/
static void address_enumerator_destroy(address_enumerator_t *data)
{
- pthread_mutex_unlock(&data->this->mutex);
+ data->this->mutex->unlock(data->this->mutex);
free(data);
}
@@ -612,7 +617,7 @@ static enumerator_t *create_address_enumerator(private_kernel_netlink_net_t *thi
data->include_down_ifaces = include_down_ifaces;
data->include_virtual_ips = include_virtual_ips;
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
return enumerator_create_nested(
enumerator_create_filter(this->ifaces->create_enumerator(this->ifaces),
(void*)filter_interfaces, data, NULL),
@@ -624,18 +629,19 @@ static enumerator_t *create_address_enumerator(private_kernel_netlink_net_t *thi
*/
static char *get_interface_name(private_kernel_netlink_net_t *this, host_t* ip)
{
- iterator_t *ifaces, *addrs;
+ enumerator_t *ifaces, *addrs;
iface_entry_t *iface;
addr_entry_t *addr;
char *name = NULL;
DBG2(DBG_KNL, "getting interface name for %H", ip);
- ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex);
- while (ifaces->iterate(ifaces, (void**)&iface))
+ this->mutex->lock(this->mutex);
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
{
- addrs = iface->addrs->create_iterator(iface->addrs, TRUE);
- while (addrs->iterate(addrs, (void**)&addr))
+ addrs = iface->addrs->create_enumerator(iface->addrs);
+ while (addrs->enumerate(addrs, &addr))
{
if (ip->ip_equals(ip, addr->ip))
{
@@ -650,6 +656,7 @@ static char *get_interface_name(private_kernel_netlink_net_t *this, host_t* ip)
}
}
ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
if (name)
{
@@ -667,14 +674,15 @@ static char *get_interface_name(private_kernel_netlink_net_t *this, host_t* ip)
*/
static int get_interface_index(private_kernel_netlink_net_t *this, char* name)
{
- iterator_t *ifaces;
+ enumerator_t *ifaces;
iface_entry_t *iface;
int ifindex = 0;
DBG2(DBG_KNL, "getting iface index for %s", name);
- ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex);
- while (ifaces->iterate(ifaces, (void**)&iface))
+ this->mutex->lock(this->mutex);
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
{
if (streq(name, iface->ifname))
{
@@ -683,6 +691,7 @@ static int get_interface_index(private_kernel_netlink_net_t *this, char* name)
}
}
ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
if (ifindex == 0)
{
@@ -692,6 +701,28 @@ static int get_interface_index(private_kernel_netlink_net_t *this, char* name)
}
/**
+ * Check if an interface with a given index is up
+ */
+static bool is_interface_up(private_kernel_netlink_net_t *this, int index)
+{
+ enumerator_t *ifaces;
+ iface_entry_t *iface;
+ bool up = FALSE;
+
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
+ {
+ if (iface->ifindex == index)
+ {
+ up = iface->flags & IFF_UP;
+ break;
+ }
+ }
+ ifaces->destroy(ifaces);
+ return up;
+}
+
+/**
* check if an address (chunk) addr is in subnet (net with net_len net bits)
*/
static bool addr_in_subnet(chunk_t addr, chunk_t net, int net_len)
@@ -730,7 +761,7 @@ static bool addr_in_subnet(chunk_t addr, chunk_t net, int net_len)
static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
bool nexthop, host_t *candidate)
{
- unsigned char request[NETLINK_BUFFER_SIZE];
+ netlink_buf_t request;
struct nlmsghdr *hdr, *out, *current;
struct rtmsg *msg;
chunk_t chunk;
@@ -763,6 +794,7 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
DBG1(DBG_KNL, "getting address to %H failed", dest);
return NULL;
}
+ this->mutex->lock(this->mutex);
current = out;
while (NLMSG_OK(current, len))
{
@@ -776,6 +808,9 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
size_t rtasize;
chunk_t rta_gtw, rta_src, rta_dst;
u_int32_t rta_oif = 0;
+ enumerator_t *ifaces, *addrs;
+ iface_entry_t *iface;
+ addr_entry_t *addr;
rta_gtw = rta_src = rta_dst = chunk_empty;
msg = (struct rtmsg*)(NLMSG_DATA(current));
@@ -803,79 +838,80 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
}
rta = RTA_NEXT(rta, rtasize);
}
+ if (rta_oif && !is_interface_up(this, rta_oif))
+ { /* interface is down */
+ goto next;
+ }
+ if (this->routing_table != 0 &&
+ msg->rtm_table == this->routing_table)
+ { /* route is from our own ipsec routing table */
+ goto next;
+ }
+ if (msg->rtm_dst_len <= best)
+ { /* not better than a previous one */
+ goto next;
+ }
+ if (msg->rtm_dst_len != 0 &&
+ (!rta_dst.ptr ||
+ !addr_in_subnet(chunk, rta_dst, msg->rtm_dst_len)))
+ { /* is not the default route and not contained in our dst */
+ goto next;
+ }
- /* apply the route if:
- * - it is not from our own ipsec routing table
- * - is better than a previous one
- * - is the default route or
- * - its destination net contains our destination
- */
- if ((this->routing_table == 0 ||msg->rtm_table != this->routing_table)
- && msg->rtm_dst_len > best
- && (msg->rtm_dst_len == 0 || /* default route */
- (rta_dst.ptr && addr_in_subnet(chunk, rta_dst, msg->rtm_dst_len))))
+ best = msg->rtm_dst_len;
+ if (nexthop)
{
- iterator_t *ifaces, *addrs;
- iface_entry_t *iface;
- addr_entry_t *addr;
-
- best = msg->rtm_dst_len;
- if (nexthop)
- {
- DESTROY_IF(gtw);
- gtw = host_create_from_chunk(msg->rtm_family, rta_gtw, 0);
- }
- else if (rta_src.ptr)
- {
+ DESTROY_IF(gtw);
+ gtw = host_create_from_chunk(msg->rtm_family, rta_gtw, 0);
+ goto next;
+ }
+ if (rta_src.ptr)
+ {
+ DESTROY_IF(src);
+ src = host_create_from_chunk(msg->rtm_family, rta_src, 0);
+ if (get_vip_refcount(this, src))
+ { /* skip source address if it is installed by us */
DESTROY_IF(src);
- src = host_create_from_chunk(msg->rtm_family, rta_src, 0);
- if (get_vip_refcount(this, src))
- { /* skip source address if it is installed by us */
- DESTROY_IF(src);
- src = NULL;
- current = NLMSG_NEXT(current, len);
- continue;
- }
+ src = NULL;
}
- else
+ goto next;
+ }
+ /* no source addr, get one from the interfaces */
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
+ {
+ if (iface->ifindex == rta_oif &&
+ iface->flags & IFF_UP)
{
- /* no source addr, get one from the interfaces */
- ifaces = this->ifaces->create_iterator_locked(
- this->ifaces, &this->mutex);
- while (ifaces->iterate(ifaces, (void**)&iface))
+ addrs = iface->addrs->create_enumerator(iface->addrs);
+ while (addrs->enumerate(addrs, &addr))
{
- if (iface->ifindex == rta_oif)
+ chunk_t ip = addr->ip->get_address(addr->ip);
+ if ((msg->rtm_dst_len == 0 &&
+ addr->ip->get_family(addr->ip) ==
+ dest->get_family(dest)) ||
+ addr_in_subnet(ip, rta_dst, msg->rtm_dst_len))
{
- addrs = iface->addrs->create_iterator(
- iface->addrs, TRUE);
- while (addrs->iterate(addrs, (void**)&addr))
- {
- chunk_t ip = addr->ip->get_address(addr->ip);
- if ((msg->rtm_dst_len == 0 &&
- addr->ip->get_family(addr->ip) ==
- dest->get_family(dest)) ||
- addr_in_subnet(ip, rta_dst, msg->rtm_dst_len))
- {
- DESTROY_IF(src);
- src = addr->ip->clone(addr->ip);
- break;
- }
- }
- addrs->destroy(addrs);
+ DESTROY_IF(src);
+ src = addr->ip->clone(addr->ip);
+ break;
}
}
- ifaces->destroy(ifaces);
+ addrs->destroy(addrs);
}
}
- /* FALL through */
+ ifaces->destroy(ifaces);
+ goto next;
}
default:
+ next:
current = NLMSG_NEXT(current, len);
continue;
}
break;
}
free(out);
+ this->mutex->unlock(this->mutex);
if (nexthop)
{
@@ -912,7 +948,7 @@ static host_t* get_nexthop(private_kernel_netlink_net_t *this, host_t *dest)
static status_t manage_ipaddr(private_kernel_netlink_net_t *this, int nlmsg_type,
int flags, int if_index, host_t *ip)
{
- unsigned char request[NETLINK_BUFFER_SIZE];
+ netlink_buf_t request;
struct nlmsghdr *hdr;
struct ifaddrmsg *msg;
chunk_t chunk;
@@ -946,18 +982,19 @@ static status_t add_ip(private_kernel_netlink_net_t *this,
{
iface_entry_t *iface;
addr_entry_t *addr;
- iterator_t *addrs, *ifaces;
+ enumerator_t *addrs, *ifaces;
int ifindex;
DBG2(DBG_KNL, "adding virtual IP %H", virtual_ip);
- ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex);
- while (ifaces->iterate(ifaces, (void**)&iface))
+ this->mutex->lock(this->mutex);
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
{
bool iface_found = FALSE;
- addrs = iface->addrs->create_iterator(iface->addrs, TRUE);
- while (addrs->iterate(addrs, (void**)&addr))
+ addrs = iface->addrs->create_enumerator(iface->addrs);
+ while (addrs->enumerate(addrs, &addr))
{
if (iface_ip->ip_equals(iface_ip, addr->ip))
{
@@ -970,6 +1007,7 @@ static status_t add_ip(private_kernel_netlink_net_t *this,
virtual_ip, iface->ifname);
addrs->destroy(addrs);
ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
return SUCCESS;
}
}
@@ -990,17 +1028,20 @@ static status_t add_ip(private_kernel_netlink_net_t *this,
{
while (get_vip_refcount(this, virtual_ip) == 0)
{ /* wait until address appears */
- pthread_cond_wait(&this->cond, &this->mutex);
+ this->condvar->wait(this->condvar, this->mutex);
}
ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
return SUCCESS;
}
ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
DBG1(DBG_KNL, "adding virtual IP %H failed", virtual_ip);
return FAILED;
}
}
ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
DBG1(DBG_KNL, "interface address %H not found, unable to install"
"virtual IP %H", iface_ip, virtual_ip);
@@ -1014,17 +1055,18 @@ static status_t del_ip(private_kernel_netlink_net_t *this, host_t *virtual_ip)
{
iface_entry_t *iface;
addr_entry_t *addr;
- iterator_t *addrs, *ifaces;
+ enumerator_t *addrs, *ifaces;
status_t status;
int ifindex;
DBG2(DBG_KNL, "deleting virtual IP %H", virtual_ip);
- ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex);
- while (ifaces->iterate(ifaces, (void**)&iface))
+ this->mutex->lock(this->mutex);
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
{
- addrs = iface->addrs->create_iterator(iface->addrs, TRUE);
- while (addrs->iterate(addrs, (void**)&addr))
+ addrs = iface->addrs->create_enumerator(iface->addrs);
+ while (addrs->enumerate(addrs, &addr))
{
if (virtual_ip->ip_equals(virtual_ip, addr->ip))
{
@@ -1037,11 +1079,12 @@ static status_t del_ip(private_kernel_netlink_net_t *this, host_t *virtual_ip)
{ /* wait until the address is really gone */
while (get_vip_refcount(this, virtual_ip) > 0)
{
- pthread_cond_wait(&this->cond, &this->mutex);
+ this->condvar->wait(this->condvar, this->mutex);
}
}
addrs->destroy(addrs);
ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
return status;
}
else
@@ -1052,12 +1095,14 @@ static status_t del_ip(private_kernel_netlink_net_t *this, host_t *virtual_ip)
virtual_ip);
addrs->destroy(addrs);
ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
return SUCCESS;
}
}
addrs->destroy(addrs);
}
ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
DBG2(DBG_KNL, "virtual IP %H not cached, unable to delete", virtual_ip);
return FAILED;
@@ -1071,7 +1116,7 @@ static status_t manage_srcroute(private_kernel_netlink_net_t *this, int nlmsg_ty
int flags, chunk_t dst_net, u_int8_t prefixlen,
host_t *gateway, host_t *src_ip, char *if_name)
{
- unsigned char request[NETLINK_BUFFER_SIZE];
+ netlink_buf_t request;
struct nlmsghdr *hdr;
struct rtmsg *msg;
int ifindex;
@@ -1151,11 +1196,11 @@ status_t del_route(private_kernel_netlink_net_t *this, chunk_t dst_net,
*/
static status_t init_address_list(private_kernel_netlink_net_t *this)
{
- char request[NETLINK_BUFFER_SIZE];
+ netlink_buf_t request;
struct nlmsghdr *out, *current, *in;
struct rtgenmsg *msg;
size_t len;
- iterator_t *ifaces, *addrs;
+ enumerator_t *ifaces, *addrs;
iface_entry_t *iface;
addr_entry_t *addr;
@@ -1217,14 +1262,15 @@ static status_t init_address_list(private_kernel_netlink_net_t *this)
}
free(out);
- ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex);
- while (ifaces->iterate(ifaces, (void**)&iface))
+ this->mutex->lock(this->mutex);
+ ifaces = this->ifaces->create_enumerator(this->ifaces);
+ while (ifaces->enumerate(ifaces, &iface))
{
if (iface->flags & IFF_UP)
{
DBG1(DBG_KNL, " %s", iface->ifname);
- addrs = iface->addrs->create_iterator(iface->addrs, TRUE);
- while (addrs->iterate(addrs, (void**)&addr))
+ addrs = iface->addrs->create_enumerator(iface->addrs);
+ while (addrs->enumerate(addrs, (void**)&addr))
{
DBG1(DBG_KNL, " %H", addr->ip);
}
@@ -1232,6 +1278,7 @@ static status_t init_address_list(private_kernel_netlink_net_t *this)
}
}
ifaces->destroy(ifaces);
+ this->mutex->unlock(this->mutex);
return SUCCESS;
}
@@ -1241,7 +1288,7 @@ static status_t init_address_list(private_kernel_netlink_net_t *this)
static status_t manage_rule(private_kernel_netlink_net_t *this, int nlmsg_type,
u_int32_t table, u_int32_t prio)
{
- unsigned char request[NETLINK_BUFFER_SIZE];
+ netlink_buf_t request;
struct nlmsghdr *hdr;
struct rtmsg *msg;
chunk_t chunk;
@@ -1284,6 +1331,8 @@ static void destroy(private_kernel_netlink_net_t *this)
close(this->socket_events);
this->socket->destroy(this->socket);
this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
+ this->condvar->destroy(this->condvar);
+ this->mutex->destroy(this->mutex);
free(this);
}
@@ -1308,8 +1357,8 @@ kernel_netlink_net_t *kernel_netlink_net_create()
/* private members */
this->ifaces = linked_list_create();
- pthread_mutex_init(&this->mutex, NULL);
- pthread_cond_init(&this->cond, NULL);
+ this->mutex = mutex_create(MUTEX_DEFAULT);
+ this->condvar = condvar_create(CONDVAR_DEFAULT);
timerclear(&this->last_roam);
this->routing_table = lib->settings->get_int(lib->settings,
"charon.routing_table", IPSEC_ROUTING_TABLE);
diff --git a/src/charon/plugins/kernel_netlink/kernel_netlink_shared.c b/src/charon/plugins/kernel_netlink/kernel_netlink_shared.c
index 55d08c5e5..3de56bf48 100644
--- a/src/charon/plugins/kernel_netlink/kernel_netlink_shared.c
+++ b/src/charon/plugins/kernel_netlink/kernel_netlink_shared.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: kernel_netlink_shared.c 4350 2008-09-18 15:16:43Z tobias $
+ * $Id: kernel_netlink_shared.c 4579 2008-11-05 11:29:56Z martin $
*/
#include <sys/socket.h>
@@ -24,6 +24,7 @@
#include "kernel_netlink_shared.h"
#include <daemon.h>
+#include <utils/mutex.h>
typedef struct private_netlink_socket_t private_netlink_socket_t;
@@ -39,7 +40,7 @@ struct private_netlink_socket_t {
/**
* mutex to lock access to netlink socket
*/
- pthread_mutex_t mutex;
+ mutex_t *mutex;
/**
* current sequence number for netlink request
@@ -63,7 +64,7 @@ static status_t netlink_send(private_netlink_socket_t *this, struct nlmsghdr *in
chunk_t result = chunk_empty, tmp;
struct nlmsghdr *msg, peek;
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
in->nlmsg_seq = ++this->seq;
in->nlmsg_pid = getpid();
@@ -85,7 +86,7 @@ static status_t netlink_send(private_netlink_socket_t *this, struct nlmsghdr *in
/* interrupted, try again */
continue;
}
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
DBG1(DBG_KNL, "error sending to netlink socket: %s", strerror(errno));
return FAILED;
}
@@ -117,14 +118,14 @@ static status_t netlink_send(private_netlink_socket_t *this, struct nlmsghdr *in
continue;
}
DBG1(DBG_KNL, "error reading from netlink socket: %s", strerror(errno));
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
free(result.ptr);
return FAILED;
}
if (!NLMSG_OK(msg, len))
{
DBG1(DBG_KNL, "received corrupted netlink message");
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
free(result.ptr);
return FAILED;
}
@@ -135,7 +136,7 @@ static status_t netlink_send(private_netlink_socket_t *this, struct nlmsghdr *in
{
continue;
}
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
free(result.ptr);
return FAILED;
}
@@ -161,7 +162,7 @@ static status_t netlink_send(private_netlink_socket_t *this, struct nlmsghdr *in
*out_len = result.len;
*out = (struct nlmsghdr*)result.ptr;
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
return SUCCESS;
}
@@ -221,6 +222,7 @@ static status_t netlink_send_ack(private_netlink_socket_t *this, struct nlmsghdr
static void destroy(private_netlink_socket_t *this)
{
close(this->socket);
+ this->mutex->destroy(this->mutex);
free(this);
}
@@ -238,7 +240,7 @@ netlink_socket_t *netlink_socket_create(int protocol) {
/* private members */
this->seq = 200;
- pthread_mutex_init(&this->mutex, NULL);
+ this->mutex = mutex_create(MUTEX_DEFAULT);
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
diff --git a/src/charon/plugins/kernel_netlink/kernel_netlink_shared.h b/src/charon/plugins/kernel_netlink/kernel_netlink_shared.h
index 6428cc9a2..90e464796 100644
--- a/src/charon/plugins/kernel_netlink/kernel_netlink_shared.h
+++ b/src/charon/plugins/kernel_netlink/kernel_netlink_shared.h
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: kernel_netlink_shared.h 4350 2008-09-18 15:16:43Z tobias $
+ * $Id: kernel_netlink_shared.h 4660 2008-11-14 14:23:11Z martin $
*/
#ifndef KERNEL_NETLINK_SHARED_H_
@@ -20,7 +20,15 @@
#include <library.h>
-#define NETLINK_BUFFER_SIZE 1024
+#include <linux/rtnetlink.h>
+
+/**
+ * General purpose netlink buffer.
+ *
+ * 1024 byte is currently sufficient for all operations. Some platform
+ * require an enforced aligment to four bytes (e.g. ARM).
+ */
+typedef u_char netlink_buf_t[1024] __attribute__((aligned(RTA_ALIGNTO)));
typedef struct netlink_socket_t netlink_socket_t;
diff --git a/src/charon/plugins/kernel_pfkey/Makefile.am b/src/charon/plugins/kernel_pfkey/Makefile.am
new file mode 100644
index 000000000..c9d66b5de
--- /dev/null
+++ b/src/charon/plugins/kernel_pfkey/Makefile.am
@@ -0,0 +1,10 @@
+
+INCLUDES = -I${linuxdir} -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
+
+AM_CFLAGS = -rdynamic
+
+plugin_LTLIBRARIES = libstrongswan-kernel-pfkey.la
+
+libstrongswan_kernel_pfkey_la_SOURCES = kernel_pfkey_plugin.h kernel_pfkey_plugin.c \
+ kernel_pfkey_ipsec.h kernel_pfkey_ipsec.c
+libstrongswan_kernel_pfkey_la_LDFLAGS = -module
diff --git a/src/charon/plugins/kernel_pfkey/Makefile.in b/src/charon/plugins/kernel_pfkey/Makefile.in
new file mode 100644
index 000000000..41bad9715
--- /dev/null
+++ b/src/charon/plugins/kernel_pfkey/Makefile.in
@@ -0,0 +1,501 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/charon/plugins/kernel_pfkey
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(plugindir)"
+pluginLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+libstrongswan_kernel_pfkey_la_LIBADD =
+am_libstrongswan_kernel_pfkey_la_OBJECTS = kernel_pfkey_plugin.lo \
+ kernel_pfkey_ipsec.lo
+libstrongswan_kernel_pfkey_la_OBJECTS = \
+ $(am_libstrongswan_kernel_pfkey_la_OBJECTS)
+libstrongswan_kernel_pfkey_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_kernel_pfkey_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_kernel_pfkey_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_kernel_pfkey_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@
+IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LINUX_HEADERS = @LINUX_HEADERS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+confdir = @confdir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libstrongswan_plugins = @libstrongswan_plugins@
+linuxdir = @linuxdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+resolv_conf = @resolv_conf@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+simreader = @simreader@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+INCLUDES = -I${linuxdir} -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
+AM_CFLAGS = -rdynamic
+plugin_LTLIBRARIES = libstrongswan-kernel-pfkey.la
+libstrongswan_kernel_pfkey_la_SOURCES = kernel_pfkey_plugin.h kernel_pfkey_plugin.c \
+ kernel_pfkey_ipsec.h kernel_pfkey_ipsec.c
+
+libstrongswan_kernel_pfkey_la_LDFLAGS = -module
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/kernel_pfkey/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/charon/plugins/kernel_pfkey/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-kernel-pfkey.la: $(libstrongswan_kernel_pfkey_la_OBJECTS) $(libstrongswan_kernel_pfkey_la_DEPENDENCIES)
+ $(libstrongswan_kernel_pfkey_la_LINK) -rpath $(plugindir) $(libstrongswan_kernel_pfkey_la_OBJECTS) $(libstrongswan_kernel_pfkey_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_pfkey_ipsec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kernel_pfkey_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+
+# 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/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
new file mode 100644
index 000000000..77f3cbed8
--- /dev/null
+++ b/src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
@@ -0,0 +1,1991 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008 Andreas Steffen
+ * 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: kernel_pfkey_ipsec.c 4662 2008-11-16 21:19:58Z andreas $
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdint.h>
+#include <linux/ipsec.h>
+#include <linux/pfkeyv2.h>
+#include <linux/udp.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <errno.h>
+
+#include "kernel_pfkey_ipsec.h"
+
+#include <daemon.h>
+#include <utils/host.h>
+#include <utils/mutex.h>
+#include <processing/jobs/callback_job.h>
+#include <processing/jobs/acquire_job.h>
+#include <processing/jobs/migrate_job.h>
+#include <processing/jobs/rekey_child_sa_job.h>
+#include <processing/jobs/delete_child_sa_job.h>
+#include <processing/jobs/update_sa_job.h>
+
+/** from linux/in.h */
+#ifndef IP_IPSEC_POLICY
+#define IP_IPSEC_POLICY 16
+#endif
+
+/** default priority of installed policies */
+#define PRIO_LOW 3000
+#define PRIO_HIGH 2000
+
+/** buffer size for PF_KEY messages */
+#define PFKEY_BUFFER_SIZE 4096
+
+/** PF_KEY messages are 64 bit aligned */
+#define PFKEY_ALIGNMENT 8
+/** aligns len to 64 bits */
+#define PFKEY_ALIGN(len) (((len) + PFKEY_ALIGNMENT - 1) & ~(PFKEY_ALIGNMENT - 1))
+/** calculates the properly padded length in 64 bit chunks */
+#define PFKEY_LEN(len) ((PFKEY_ALIGN(len) / PFKEY_ALIGNMENT))
+/** calculates user mode length i.e. in bytes */
+#define PFKEY_USER_LEN(len) ((len) * PFKEY_ALIGNMENT)
+
+/** given a PF_KEY message header and an extension this updates the length in the header */
+#define PFKEY_EXT_ADD(msg, ext) ((msg)->sadb_msg_len += ((struct sadb_ext*)ext)->sadb_ext_len)
+/** given a PF_KEY message header this returns a pointer to the next extension */
+#define PFKEY_EXT_ADD_NEXT(msg) ((struct sadb_ext*)(((char*)(msg)) + PFKEY_USER_LEN((msg)->sadb_msg_len)))
+/** copy an extension and append it to a PF_KEY message */
+#define PFKEY_EXT_COPY(msg, ext) (PFKEY_EXT_ADD(msg, memcpy(PFKEY_EXT_ADD_NEXT(msg), ext, PFKEY_USER_LEN(((struct sadb_ext*)ext)->sadb_ext_len))))
+/** given a PF_KEY extension this returns a pointer to the next extension */
+#define PFKEY_EXT_NEXT(ext) ((struct sadb_ext*)(((char*)(ext)) + PFKEY_USER_LEN(((struct sadb_ext*)ext)->sadb_ext_len)))
+/** given a PF_KEY extension this returns a pointer to the next extension also updates len (len in 64 bit words) */
+#define PFKEY_EXT_NEXT_LEN(ext,len) ((len) -= (ext)->sadb_ext_len, PFKEY_EXT_NEXT(ext))
+/** true if ext has a valid length and len is large enough to contain ext (assuming len in 64 bit words) */
+#define PFKEY_EXT_OK(ext,len) ((len) >= PFKEY_LEN(sizeof(struct sadb_ext)) && \
+ (ext)->sadb_ext_len >= PFKEY_LEN(sizeof(struct sadb_ext)) && \
+ (ext)->sadb_ext_len <= (len))
+
+typedef struct private_kernel_pfkey_ipsec_t private_kernel_pfkey_ipsec_t;
+
+/**
+ * Private variables and functions of kernel_pfkey class.
+ */
+struct private_kernel_pfkey_ipsec_t
+{
+ /**
+ * Public part of the kernel_pfkey_t object.
+ */
+ kernel_pfkey_ipsec_t public;
+
+ /**
+ * mutex to lock access to various lists
+ */
+ mutex_t *mutex;
+
+ /**
+ * List of installed policies (policy_entry_t)
+ */
+ linked_list_t *policies;
+
+ /**
+ * whether to install routes along policies
+ */
+ bool install_routes;
+
+ /**
+ * job receiving PF_KEY events
+ */
+ callback_job_t *job;
+
+ /**
+ * mutex to lock access to the PF_KEY socket
+ */
+ mutex_t *mutex_pfkey;
+
+ /**
+ * PF_KEY socket to communicate with the kernel
+ */
+ int socket;
+
+ /**
+ * PF_KEY socket to receive acquire and expire events
+ */
+ int socket_events;
+
+ /**
+ * sequence number for messages sent to the kernel
+ */
+ int seq;
+};
+
+typedef struct route_entry_t route_entry_t;
+
+/**
+ * installed routing entry
+ */
+struct route_entry_t {
+ /** Name of the interface the route is bound to */
+ char *if_name;
+
+ /** Source ip of the route */
+ host_t *src_ip;
+
+ /** gateway for this route */
+ host_t *gateway;
+
+ /** Destination net */
+ chunk_t dst_net;
+
+ /** Destination net prefixlen */
+ u_int8_t prefixlen;
+};
+
+/**
+ * destroy an route_entry_t object
+ */
+static void route_entry_destroy(route_entry_t *this)
+{
+ free(this->if_name);
+ this->src_ip->destroy(this->src_ip);
+ this->gateway->destroy(this->gateway);
+ chunk_free(&this->dst_net);
+ free(this);
+}
+
+typedef struct policy_entry_t policy_entry_t;
+
+/**
+ * installed kernel policy.
+ */
+struct policy_entry_t {
+
+ /** reqid of this policy */
+ u_int32_t reqid;
+
+ /** index assigned by the kernel */
+ u_int32_t index;
+
+ /** direction of this policy: in, out, forward */
+ u_int8_t direction;
+
+ /** parameters of installed policy */
+ struct {
+ /** subnet and port */
+ host_t *net;
+ /** subnet mask */
+ u_int8_t mask;
+ /** protocol */
+ u_int8_t proto;
+ } src, dst;
+
+ /** associated route installed for this policy */
+ route_entry_t *route;
+
+ /** by how many CHILD_SA's this policy is used */
+ u_int refcount;
+};
+
+/**
+ * create a policy_entry_t object
+ */
+static policy_entry_t *create_policy_entry(traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t dir, u_int32_t reqid)
+{
+ policy_entry_t *policy = malloc_thing(policy_entry_t);
+ policy->reqid = reqid;
+ policy->index = 0;
+ policy->direction = dir;
+ policy->route = NULL;
+ policy->refcount = 0;
+
+ src_ts->to_subnet(src_ts, &policy->src.net, &policy->src.mask);
+ dst_ts->to_subnet(dst_ts, &policy->dst.net, &policy->dst.mask);
+
+ /* src or dest proto may be "any" (0), use more restrictive one */
+ policy->src.proto = max(src_ts->get_protocol(src_ts), dst_ts->get_protocol(dst_ts));
+ policy->src.proto = policy->src.proto ? policy->src.proto : IPSEC_PROTO_ANY;
+ policy->dst.proto = policy->src.proto;
+
+ return policy;
+}
+
+/**
+ * destroy a policy_entry_t object
+ */
+static void policy_entry_destroy(policy_entry_t *this)
+{
+ DESTROY_IF(this->src.net);
+ DESTROY_IF(this->dst.net);
+ if (this->route)
+ {
+ route_entry_destroy(this->route);
+ }
+ free(this);
+}
+
+/**
+ * compares two policy_entry_t
+ */
+static inline bool policy_entry_equals(policy_entry_t *current, policy_entry_t *policy)
+{
+ return current->direction == policy->direction &&
+ current->src.proto == policy->src.proto &&
+ current->dst.proto == policy->dst.proto &&
+ current->src.mask == policy->src.mask &&
+ current->dst.mask == policy->dst.mask &&
+ current->src.net->equals(current->src.net, policy->src.net) &&
+ current->dst.net->equals(current->dst.net, policy->dst.net);
+}
+
+/**
+ * compare the given kernel index with that of a policy
+ */
+static inline bool policy_entry_match_byindex(policy_entry_t *current, u_int32_t *index)
+{
+ return current->index == *index;
+}
+
+typedef struct pfkey_msg_t pfkey_msg_t;
+
+struct pfkey_msg_t
+{
+ /**
+ * PF_KEY message base
+ */
+ struct sadb_msg *msg;
+
+
+ /**
+ * PF_KEY message extensions
+ */
+ union {
+ struct sadb_ext *ext[SADB_EXT_MAX + 1];
+ struct {
+ struct sadb_ext *reserved; /* SADB_EXT_RESERVED */
+ struct sadb_sa *sa; /* SADB_EXT_SA */
+ struct sadb_lifetime *lft_current; /* SADB_EXT_LIFETIME_CURRENT */
+ struct sadb_lifetime *lft_hard; /* SADB_EXT_LIFETIME_HARD */
+ struct sadb_lifetime *lft_soft; /* SADB_EXT_LIFETIME_SOFT */
+ struct sadb_address *src; /* SADB_EXT_ADDRESS_SRC */
+ struct sadb_address *dst; /* SADB_EXT_ADDRESS_DST */
+ struct sadb_address *proxy; /* SADB_EXT_ADDRESS_PROXY */
+ struct sadb_key *key_auth; /* SADB_EXT_KEY_AUTH */
+ struct sadb_key *key_encr; /* SADB_EXT_KEY_ENCRYPT */
+ struct sadb_ident *id_src; /* SADB_EXT_IDENTITY_SRC */
+ struct sadb_ident *id_dst; /* SADB_EXT_IDENTITY_DST */
+ struct sadb_sens *sensitivity; /* SADB_EXT_SENSITIVITY */
+ struct sadb_prop *proposal; /* SADB_EXT_PROPOSAL */
+ struct sadb_supported *supported_auth; /* SADB_EXT_SUPPORTED_AUTH */
+ struct sadb_supported *supported_encr; /* SADB_EXT_SUPPORTED_ENCRYPT */
+ struct sadb_spirange *spirange; /* SADB_EXT_SPIRANGE */
+ struct sadb_x_kmprivate *x_kmprivate; /* SADB_X_EXT_KMPRIVATE */
+ struct sadb_x_policy *x_policy; /* SADB_X_EXT_POLICY */
+ struct sadb_x_sa2 *x_sa2; /* SADB_X_EXT_SA2 */
+ struct sadb_x_nat_t_type *x_natt_type; /* SADB_X_EXT_NAT_T_TYPE */
+ struct sadb_x_nat_t_port *x_natt_sport; /* SADB_X_EXT_NAT_T_SPORT */
+ struct sadb_x_nat_t_port *x_natt_dport; /* SADB_X_EXT_NAT_T_DPORT */
+ struct sadb_address *x_natt_oa; /* SADB_X_EXT_NAT_T_OA */
+ struct sadb_x_sec_ctx *x_sec_ctx; /* SADB_X_EXT_SEC_CTX */
+ struct sadb_x_kmaddress *x_kmaddress; /* SADB_X_EXT_KMADDRESS */
+ } __attribute__((__packed__));
+ };
+};
+
+ENUM(sadb_ext_type_names, SADB_EXT_RESERVED, SADB_X_EXT_KMADDRESS,
+ "SADB_EXT_RESERVED",
+ "SADB_EXT_SA",
+ "SADB_EXT_LIFETIME_CURRENT",
+ "SADB_EXT_LIFETIME_HARD",
+ "SADB_EXT_LIFETIME_SOFT",
+ "SADB_EXT_ADDRESS_SRC",
+ "SADB_EXT_ADDRESS_DST",
+ "SADB_EXT_ADDRESS_PROXY",
+ "SADB_EXT_KEY_AUTH",
+ "SADB_EXT_KEY_ENCRYPT",
+ "SADB_EXT_IDENTITY_SRC",
+ "SADB_EXT_IDENTITY_DST",
+ "SADB_EXT_SENSITIVITY",
+ "SADB_EXT_PROPOSAL",
+ "SADB_EXT_SUPPORTED_AUTH",
+ "SADB_EXT_SUPPORTED_ENCRYPT",
+ "SADB_EXT_SPIRANGE",
+ "SADB_X_EXT_KMPRIVATE",
+ "SADB_X_EXT_POLICY",
+ "SADB_X_EXT_SA2",
+ "SADB_X_EXT_NAT_T_TYPE",
+ "SADB_X_EXT_NAT_T_SPORT",
+ "SADB_X_EXT_NAT_T_DPORT",
+ "SADB_X_EXT_NAT_T_OA",
+ "SADB_X_EXT_SEC_CTX",
+ "SADB_X_EXT_KMADDRESS"
+);
+/**
+ * convert a IKEv2 specific protocol identifier to the PF_KEY sa type
+ */
+static u_int8_t proto_ike2satype(protocol_id_t proto)
+{
+ switch (proto)
+ {
+ case PROTO_ESP:
+ return SADB_SATYPE_ESP;
+ case PROTO_AH:
+ return SADB_SATYPE_AH;
+ case IPPROTO_COMP:
+ return SADB_X_SATYPE_IPCOMP;
+ default:
+ return proto;
+ }
+}
+
+/**
+ * convert a PF_KEY sa type to a IKEv2 specific protocol identifier
+ */
+static protocol_id_t proto_satype2ike(u_int8_t proto)
+{
+ switch (proto)
+ {
+ case SADB_SATYPE_ESP:
+ return PROTO_ESP;
+ case SADB_SATYPE_AH:
+ return PROTO_AH;
+ case SADB_X_SATYPE_IPCOMP:
+ return IPPROTO_COMP;
+ default:
+ return proto;
+ }
+}
+
+/**
+ * convert a IKEv2 specific protocol identifier to the IP protocol identifier
+ */
+static u_int8_t proto_ike2ip(protocol_id_t proto)
+{
+ switch (proto)
+ {
+ case PROTO_ESP:
+ return IPPROTO_ESP;
+ case PROTO_AH:
+ return IPPROTO_AH;
+ default:
+ return proto;
+ }
+}
+
+/**
+ * convert the general ipsec mode to the one defined in ipsec.h
+ */
+static u_int8_t mode2kernel(ipsec_mode_t mode)
+{
+ switch (mode)
+ {
+ case MODE_TRANSPORT:
+ return IPSEC_MODE_TRANSPORT;
+ case MODE_TUNNEL:
+ return IPSEC_MODE_TUNNEL;
+ case MODE_BEET:
+ return IPSEC_MODE_BEET;
+ default:
+ return mode;
+ }
+}
+
+/**
+ * convert the general policy direction to the one defined in ipsec.h
+ */
+static u_int8_t dir2kernel(policy_dir_t dir)
+{
+ switch (dir)
+ {
+ case POLICY_IN:
+ return IPSEC_DIR_INBOUND;
+ case POLICY_OUT:
+ return IPSEC_DIR_OUTBOUND;
+ case POLICY_FWD:
+ return IPSEC_DIR_FWD;
+ default:
+ return dir;
+ }
+}
+
+/**
+ * convert the policy direction in ipsec.h to the general one.
+ */
+static policy_dir_t kernel2dir(u_int8_t dir)
+{
+ switch (dir)
+ {
+ case IPSEC_DIR_INBOUND:
+ return POLICY_IN;
+ case IPSEC_DIR_OUTBOUND:
+ return POLICY_OUT;
+ case IPSEC_DIR_FWD:
+ return POLICY_FWD;
+ default:
+ return dir;
+ }
+}
+typedef struct kernel_algorithm_t kernel_algorithm_t;
+
+/**
+ * Mapping of IKEv2 algorithms to PF_KEY algorithms
+ */
+struct kernel_algorithm_t {
+ /**
+ * Identifier specified in IKEv2
+ */
+ int ikev2;
+
+ /**
+ * Identifier as defined in pfkeyv2.h
+ */
+ int kernel;
+};
+
+#define END_OF_LIST -1
+
+/**
+ * Algorithms for encryption
+ */
+static kernel_algorithm_t encryption_algs[] = {
+/* {ENCR_DES_IV64, 0 }, */
+ {ENCR_DES, SADB_EALG_DESCBC },
+ {ENCR_3DES, SADB_EALG_3DESCBC },
+/* {ENCR_RC5, 0 }, */
+/* {ENCR_IDEA, 0 }, */
+ {ENCR_CAST, SADB_X_EALG_CASTCBC },
+ {ENCR_BLOWFISH, SADB_X_EALG_BLOWFISHCBC },
+/* {ENCR_3IDEA, 0 }, */
+/* {ENCR_DES_IV32, 0 }, */
+ {ENCR_NULL, SADB_EALG_NULL },
+ {ENCR_AES_CBC, SADB_X_EALG_AESCBC },
+/* {ENCR_AES_CTR, SADB_X_EALG_AESCTR }, */
+/* {ENCR_AES_CCM_ICV8, SADB_X_EALG_AES_CCM_ICV8 }, */
+/* {ENCR_AES_CCM_ICV12, SADB_X_EALG_AES_CCM_ICV12 }, */
+/* {ENCR_AES_CCM_ICV16, SADB_X_EALG_AES_CCM_ICV16 }, */
+/* {ENCR_AES_GCM_ICV8, SADB_X_EALG_AES_GCM_ICV8 }, */
+/* {ENCR_AES_GCM_ICV12, SADB_X_EALG_AES_GCM_ICV12 }, */
+/* {ENCR_AES_GCM_ICV16, SADB_X_EALG_AES_GCM_ICV16 }, */
+ {END_OF_LIST, 0 },
+};
+
+/**
+ * Algorithms for integrity protection
+ */
+static kernel_algorithm_t integrity_algs[] = {
+ {AUTH_HMAC_MD5_96, SADB_AALG_MD5HMAC },
+ {AUTH_HMAC_SHA1_96, SADB_AALG_SHA1HMAC },
+ {AUTH_HMAC_SHA2_256_128, SADB_X_AALG_SHA2_256HMAC },
+ {AUTH_HMAC_SHA2_384_192, SADB_X_AALG_SHA2_384HMAC },
+ {AUTH_HMAC_SHA2_512_256, SADB_X_AALG_SHA2_512HMAC },
+/* {AUTH_DES_MAC, 0, }, */
+/* {AUTH_KPDK_MD5, 0, }, */
+ {AUTH_AES_XCBC_96, SADB_X_AALG_AES_XCBC_MAC, },
+ {END_OF_LIST, 0, },
+};
+
+#if 0
+/**
+ * Algorithms for IPComp, unused yet
+ */
+static kernel_algorithm_t compression_algs[] = {
+/* {IPCOMP_OUI, 0 }, */
+ {IPCOMP_DEFLATE, SADB_X_CALG_DEFLATE },
+ {IPCOMP_LZS, SADB_X_CALG_LZS },
+ {IPCOMP_LZJH, SADB_X_CALG_LZJH },
+ {END_OF_LIST, 0 },
+};
+#endif
+
+/**
+ * Look up a kernel algorithm ID and its key size
+ */
+static int lookup_algorithm(kernel_algorithm_t *list, int ikev2)
+{
+ while (list->ikev2 != END_OF_LIST)
+ {
+ if (ikev2 == list->ikev2)
+ {
+ return list->kernel;
+ }
+ list++;
+ }
+ return 0;
+}
+
+/**
+ * add a host behind a sadb_address extension
+ */
+static void host2ext(host_t *host, struct sadb_address *ext)
+{
+ sockaddr_t *host_addr = host->get_sockaddr(host);
+ socklen_t *len = host->get_sockaddr_len(host);
+ memcpy((char*)(ext + 1), host_addr, *len);
+ ext->sadb_address_len = PFKEY_LEN(sizeof(*ext) + *len);
+}
+
+/**
+ * add udp encap extensions to a sadb_msg
+ */
+static void add_encap_ext(struct sadb_msg *msg, host_t *src, host_t *dst)
+{
+ struct sadb_x_nat_t_type* nat_type;
+ struct sadb_x_nat_t_port* nat_port;
+
+ nat_type = (struct sadb_x_nat_t_type*)PFKEY_EXT_ADD_NEXT(msg);
+ nat_type->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
+ nat_type->sadb_x_nat_t_type_len = PFKEY_LEN(sizeof(struct sadb_x_nat_t_type));
+ nat_type->sadb_x_nat_t_type_type = UDP_ENCAP_ESPINUDP;
+ PFKEY_EXT_ADD(msg, nat_type);
+
+ nat_port = (struct sadb_x_nat_t_port*)PFKEY_EXT_ADD_NEXT(msg);
+ nat_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_SPORT;
+ nat_port->sadb_x_nat_t_port_len = PFKEY_LEN(sizeof(struct sadb_x_nat_t_port));
+ nat_port->sadb_x_nat_t_port_port = htons(src->get_port(src));
+ PFKEY_EXT_ADD(msg, nat_port);
+
+ nat_port = (struct sadb_x_nat_t_port*)PFKEY_EXT_ADD_NEXT(msg);
+ nat_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_DPORT;
+ nat_port->sadb_x_nat_t_port_len = PFKEY_LEN(sizeof(struct sadb_x_nat_t_port));
+ nat_port->sadb_x_nat_t_port_port = htons(dst->get_port(dst));
+ PFKEY_EXT_ADD(msg, nat_port);
+}
+
+/**
+ * Convert a sadb_address to a traffic_selector
+ */
+static traffic_selector_t* sadb_address2ts(struct sadb_address *address)
+{
+ traffic_selector_t *ts;
+ host_t *host;
+
+ /* The Linux 2.6 kernel does not set the protocol and port information
+ * in the src and dst sadb_address extensions of the SADB_ACQUIRE message.
+ */
+ host = host_create_from_sockaddr((sockaddr_t*)&address[1]) ;
+ ts = traffic_selector_create_from_subnet(host, address->sadb_address_prefixlen,
+ address->sadb_address_proto, host->get_port(host));
+ host->destroy(host);
+ return ts;
+}
+
+/**
+ * Parses a pfkey message received from the kernel
+ */
+static status_t parse_pfkey_message(struct sadb_msg *msg, pfkey_msg_t *out)
+{
+ struct sadb_ext* ext;
+ size_t len;
+
+ memset(out, 0, sizeof(pfkey_msg_t));
+ out->msg = msg;
+
+ len = msg->sadb_msg_len;
+ len -= PFKEY_LEN(sizeof(struct sadb_msg));
+
+ ext = (struct sadb_ext*)(((char*)msg) + sizeof(struct sadb_msg));
+
+ while (len >= PFKEY_LEN(sizeof(struct sadb_ext)))
+ {
+ DBG2(DBG_KNL, " %N", sadb_ext_type_names, ext->sadb_ext_type);
+ if (ext->sadb_ext_len < PFKEY_LEN(sizeof(struct sadb_ext)) ||
+ ext->sadb_ext_len > len)
+ {
+ DBG1(DBG_KNL, "length of %N extension is invalid",
+ sadb_ext_type_names, ext->sadb_ext_type);
+ break;
+ }
+
+ if ((ext->sadb_ext_type > SADB_EXT_MAX) || (!ext->sadb_ext_type))
+ {
+ DBG1(DBG_KNL, "type of PF_KEY extension (%d) is invalid", ext->sadb_ext_type);
+ break;
+ }
+
+ if (out->ext[ext->sadb_ext_type])
+ {
+ DBG1(DBG_KNL, "duplicate %N extension",
+ sadb_ext_type_names, ext->sadb_ext_type);
+ break;
+ }
+
+ out->ext[ext->sadb_ext_type] = ext;
+ ext = PFKEY_EXT_NEXT_LEN(ext, len);
+ }
+
+ if (len)
+ {
+ DBG1(DBG_KNL, "PF_KEY message length is invalid");
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Send a message to a specific PF_KEY socket and handle the response.
+ */
+static status_t pfkey_send_socket(private_kernel_pfkey_ipsec_t *this, int socket,
+ struct sadb_msg *in, struct sadb_msg **out, size_t *out_len)
+{
+ unsigned char buf[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg;
+ int in_len, len;
+
+ this->mutex_pfkey->lock(this->mutex_pfkey);
+
+ in->sadb_msg_seq = ++this->seq;
+ in->sadb_msg_pid = getpid();
+
+ in_len = PFKEY_USER_LEN(in->sadb_msg_len);
+
+ while (TRUE)
+ {
+ len = send(socket, in, in_len, 0);
+
+ if (len != in_len)
+ {
+ if (errno == EINTR)
+ {
+ /* interrupted, try again */
+ continue;
+ }
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+ DBG1(DBG_KNL, "error sending to PF_KEY socket: %s", strerror(errno));
+ return FAILED;
+ }
+ break;
+ }
+
+ while (TRUE)
+ {
+ msg = (struct sadb_msg*)buf;
+
+ len = recv(socket, buf, sizeof(buf), 0);
+
+ if (len < 0)
+ {
+ if (errno == EINTR)
+ {
+ DBG1(DBG_KNL, "got interrupted");
+ /* interrupted, try again */
+ continue;
+ }
+ DBG1(DBG_KNL, "error reading from PF_KEY socket: %s", strerror(errno));
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+ return FAILED;
+ }
+ if (len < sizeof(struct sadb_msg) ||
+ msg->sadb_msg_len < PFKEY_LEN(sizeof(struct sadb_msg)))
+ {
+ DBG1(DBG_KNL, "received corrupted PF_KEY message");
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+ return FAILED;
+ }
+ if (msg->sadb_msg_len > len / PFKEY_ALIGNMENT)
+ {
+ DBG1(DBG_KNL, "buffer was too small to receive the complete PF_KEY message");
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+ return FAILED;
+ }
+ if (msg->sadb_msg_pid != in->sadb_msg_pid)
+ {
+ DBG2(DBG_KNL, "received PF_KEY message is not intended for us");
+ continue;
+ }
+ if (msg->sadb_msg_seq != this->seq)
+ {
+ DBG1(DBG_KNL, "received PF_KEY message with invalid sequence number, "
+ "was %d expected %d", msg->sadb_msg_seq, this->seq);
+ if (msg->sadb_msg_seq < this->seq)
+ {
+ continue;
+ }
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+ return FAILED;
+ }
+ if (msg->sadb_msg_type != in->sadb_msg_type)
+ {
+ DBG2(DBG_KNL, "received PF_KEY message of wrong type, "
+ "was %d expected %d, ignoring",
+ msg->sadb_msg_type, in->sadb_msg_type);
+ }
+ break;
+ }
+
+ *out_len = len;
+ *out = (struct sadb_msg*)malloc(len);
+ memcpy(*out, buf, len);
+
+ this->mutex_pfkey->unlock(this->mutex_pfkey);
+
+ return SUCCESS;
+}
+
+/**
+ * Send a message to the default PF_KEY socket and handle the response.
+ */
+static status_t pfkey_send(private_kernel_pfkey_ipsec_t *this,
+ struct sadb_msg *in, struct sadb_msg **out, size_t *out_len)
+{
+ return pfkey_send_socket(this, this->socket, in, out, out_len);
+}
+
+/**
+ * Process a SADB_ACQUIRE message from the kernel
+ */
+static void process_acquire(private_kernel_pfkey_ipsec_t *this, struct sadb_msg* msg)
+{
+ pfkey_msg_t response;
+ u_int32_t index, reqid = 0;
+ traffic_selector_t *src_ts, *dst_ts;
+ policy_entry_t *policy;
+ job_t *job;
+
+ switch (msg->sadb_msg_satype)
+ {
+ case SADB_SATYPE_UNSPEC:
+ case SADB_SATYPE_ESP:
+ case SADB_SATYPE_AH:
+ break;
+ default:
+ /* acquire for AH/ESP only */
+ return;
+ }
+ DBG2(DBG_KNL, "received an SADB_ACQUIRE");
+
+ if (parse_pfkey_message(msg, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "parsing SADB_ACQUIRE from kernel failed");
+ return;
+ }
+
+ index = response.x_policy->sadb_x_policy_id;
+ this->mutex->lock(this->mutex);
+ if (this->policies->find_first(this->policies,
+ (linked_list_match_t)policy_entry_match_byindex, (void**)&policy, &index) == SUCCESS)
+ {
+ reqid = policy->reqid;
+ }
+ else
+ {
+ DBG1(DBG_KNL, "received an SADB_ACQUIRE with policy id %d but no matching policy found",
+ index);
+ }
+ src_ts = sadb_address2ts(response.src);
+ dst_ts = sadb_address2ts(response.dst);
+ this->mutex->unlock(this->mutex);
+
+ DBG1(DBG_KNL, "creating acquire job for policy %R === %R with reqid {%u}",
+ src_ts, dst_ts, reqid);
+ job = (job_t*)acquire_job_create(reqid, src_ts, dst_ts);
+ charon->processor->queue_job(charon->processor, job);
+}
+
+/**
+ * Process a SADB_EXPIRE message from the kernel
+ */
+static void process_expire(private_kernel_pfkey_ipsec_t *this, struct sadb_msg* msg)
+{
+ pfkey_msg_t response;
+ protocol_id_t protocol;
+ u_int32_t spi, reqid;
+ bool hard;
+ job_t *job;
+
+ DBG2(DBG_KNL, "received an SADB_EXPIRE");
+
+ if (parse_pfkey_message(msg, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "parsing SADB_EXPIRE from kernel failed");
+ return;
+ }
+
+ protocol = proto_satype2ike(msg->sadb_msg_satype);
+ spi = response.sa->sadb_sa_spi;
+ reqid = response.x_sa2->sadb_x_sa2_reqid;
+ hard = response.lft_hard != NULL;
+
+ if (protocol != PROTO_ESP && protocol != PROTO_AH)
+ {
+ DBG2(DBG_KNL, "ignoring SADB_EXPIRE for SA with SPI %.8x and reqid {%u} "
+ "which is not a CHILD_SA", ntohl(spi), reqid);
+ return;
+ }
+
+ DBG1(DBG_KNL, "creating %s job for %N CHILD_SA with SPI %.8x and reqid {%u}",
+ hard ? "delete" : "rekey", protocol_id_names,
+ protocol, ntohl(spi), reqid);
+ if (hard)
+ {
+ job = (job_t*)delete_child_sa_job_create(reqid, protocol, spi);
+ }
+ else
+ {
+ job = (job_t*)rekey_child_sa_job_create(reqid, protocol, spi);
+ }
+ charon->processor->queue_job(charon->processor, job);
+}
+
+/**
+ * Process a SADB_MIGRATE message from the kernel
+ */
+static void process_migrate(private_kernel_pfkey_ipsec_t *this, struct sadb_msg* msg)
+{
+ pfkey_msg_t response;
+ traffic_selector_t *src_ts, *dst_ts;
+ policy_dir_t dir;
+ u_int32_t reqid = 0;
+ host_t *local = NULL, *remote = NULL;
+ job_t *job;
+
+ DBG2(DBG_KNL, "received an SADB_X_MIGRATE");
+
+ if (parse_pfkey_message(msg, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "parsing SADB_X_MIGRATE from kernel failed");
+ return;
+ }
+ src_ts = sadb_address2ts(response.src);
+ dst_ts = sadb_address2ts(response.dst);
+ dir = kernel2dir(response.x_policy->sadb_x_policy_dir);
+ DBG2(DBG_KNL, " policy %R === %R %N, id %u", src_ts, dst_ts,
+ policy_dir_names, dir);
+
+ /* SADB_X_EXT_KMADDRESS is not present in unpatched kernels < 2.6.28 */
+ if (response.x_kmaddress)
+ {
+ sockaddr_t *local_addr, *remote_addr;
+ u_int32_t local_len;
+
+ local_addr = (sockaddr_t*)&response.x_kmaddress[1];
+ local = host_create_from_sockaddr(local_addr);
+ local_len = (local_addr->sa_family == AF_INET6)?
+ sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
+ remote_addr = (sockaddr_t*)((u_int8_t*)local_addr + local_len);
+ remote = host_create_from_sockaddr(remote_addr);
+ DBG2(DBG_KNL, " kmaddress: %H...%H", local, remote);
+ }
+
+ if (src_ts && dst_ts && local && remote)
+ {
+ DBG1(DBG_KNL, "creating migrate job for policy %R === %R %N with reqid {%u}",
+ src_ts, dst_ts, policy_dir_names, dir, reqid, local);
+ job = (job_t*)migrate_job_create(reqid, src_ts, dst_ts, dir,
+ local, remote);
+ charon->processor->queue_job(charon->processor, job);
+ }
+ else
+ {
+ DESTROY_IF(src_ts);
+ DESTROY_IF(dst_ts);
+ DESTROY_IF(local);
+ DESTROY_IF(remote);
+ }
+}
+
+/**
+ * Process a SADB_X_NAT_T_NEW_MAPPING message from the kernel
+ */
+static void process_mapping(private_kernel_pfkey_ipsec_t *this, struct sadb_msg* msg)
+{
+ pfkey_msg_t response;
+ u_int32_t spi, reqid;
+ host_t *host;
+ job_t *job;
+
+ DBG2(DBG_KNL, "received an SADB_X_NAT_T_NEW_MAPPING");
+
+ if (parse_pfkey_message(msg, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "parsing SADB_X_NAT_T_NEW_MAPPING from kernel failed");
+ return;
+ }
+
+ if (!response.x_sa2)
+ {
+ DBG1(DBG_KNL, "received SADB_X_NAT_T_NEW_MAPPING is missing required information");
+ return;
+ }
+
+ spi = response.sa->sadb_sa_spi;
+ reqid = response.x_sa2->sadb_x_sa2_reqid;
+
+ if (proto_satype2ike(msg->sadb_msg_satype) == PROTO_ESP)
+ {
+ sockaddr_t *sa = (sockaddr_t*)(response.dst + 1);
+ switch (sa->sa_family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in*)sa;
+ sin->sin_port = htons(response.x_natt_dport->sadb_x_nat_t_port_port);
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa;
+ sin6->sin6_port = htons(response.x_natt_dport->sadb_x_nat_t_port_port);
+ }
+ default:
+ break;
+ }
+ host = host_create_from_sockaddr(sa);
+ if (host)
+ {
+ DBG1(DBG_KNL, "NAT mappings of ESP CHILD_SA with SPI %.8x and "
+ "reqid {%u} changed, queuing update job", ntohl(spi), reqid);
+ job = (job_t*)update_sa_job_create(reqid, host);
+ charon->processor->queue_job(charon->processor, job);
+ }
+ }
+}
+
+/**
+ * Receives events from kernel
+ */
+static job_requeue_t receive_events(private_kernel_pfkey_ipsec_t *this)
+{
+ unsigned char buf[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg = (struct sadb_msg*)buf;
+ int len, oldstate;
+
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
+ len = recv(this->socket_events, buf, sizeof(buf), 0);
+ pthread_setcancelstate(oldstate, NULL);
+
+ if (len < 0)
+ {
+ switch (errno)
+ {
+ case EINTR:
+ /* interrupted, try again */
+ return JOB_REQUEUE_DIRECT;
+ case EAGAIN:
+ /* no data ready, select again */
+ return JOB_REQUEUE_DIRECT;
+ default:
+ DBG1(DBG_KNL, "unable to receive from PF_KEY event socket");
+ sleep(1);
+ return JOB_REQUEUE_FAIR;
+ }
+ }
+
+ if (len < sizeof(struct sadb_msg) ||
+ msg->sadb_msg_len < PFKEY_LEN(sizeof(struct sadb_msg)))
+ {
+ DBG2(DBG_KNL, "received corrupted PF_KEY message");
+ return JOB_REQUEUE_DIRECT;
+ }
+ if (msg->sadb_msg_pid != 0)
+ { /* not from kernel. not interested, try another one */
+ return JOB_REQUEUE_DIRECT;
+ }
+ if (msg->sadb_msg_len > len / PFKEY_ALIGNMENT)
+ {
+ DBG1(DBG_KNL, "buffer was too small to receive the complete PF_KEY message");
+ return JOB_REQUEUE_DIRECT;
+ }
+
+ switch (msg->sadb_msg_type)
+ {
+ case SADB_ACQUIRE:
+ process_acquire(this, msg);
+ break;
+ case SADB_EXPIRE:
+ process_expire(this, msg);
+ break;
+ case SADB_X_MIGRATE:
+ process_migrate(this, msg);
+ break;
+ case SADB_X_NAT_T_NEW_MAPPING:
+ process_mapping(this, msg);
+ break;
+ default:
+ break;
+ }
+
+ return JOB_REQUEUE_DIRECT;
+}
+
+/**
+ * Implementation of kernel_interface_t.get_spi.
+ */
+static status_t get_spi(private_kernel_pfkey_ipsec_t *this,
+ host_t *src, host_t *dst,
+ protocol_id_t protocol, u_int32_t reqid,
+ u_int32_t *spi)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_x_sa2 *sa2;
+ struct sadb_address *addr;
+ struct sadb_spirange *range;
+ pfkey_msg_t response;
+ u_int32_t received_spi = 0;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_GETSPI;
+ msg->sadb_msg_satype = proto_ike2satype(protocol);
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa2 = (struct sadb_x_sa2*)PFKEY_EXT_ADD_NEXT(msg);
+ sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
+ sa2->sadb_x_sa2_len = PFKEY_LEN(sizeof(struct sadb_spirange));
+ sa2->sadb_x_sa2_reqid = reqid;
+ PFKEY_EXT_ADD(msg, sa2);
+
+ addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+ host2ext(src, addr);
+ PFKEY_EXT_ADD(msg, addr);
+
+ addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+ host2ext(dst, addr);
+ PFKEY_EXT_ADD(msg, addr);
+
+ range = (struct sadb_spirange*)PFKEY_EXT_ADD_NEXT(msg);
+ range->sadb_spirange_exttype = SADB_EXT_SPIRANGE;
+ range->sadb_spirange_len = PFKEY_LEN(sizeof(struct sadb_spirange));
+ range->sadb_spirange_min = 0xc0000000;
+ range->sadb_spirange_max = 0xcFFFFFFF;
+ PFKEY_EXT_ADD(msg, range);
+
+ if (pfkey_send(this, msg, &out, &len) == SUCCESS)
+ {
+ if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "allocating SPI failed: %s (%d)",
+ strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ }
+ else if (parse_pfkey_message(out, &response) == SUCCESS)
+ {
+ received_spi = response.sa->sadb_sa_spi;
+ }
+ free(out);
+ }
+
+ if (received_spi == 0)
+ {
+ return FAILED;
+ }
+
+ *spi = received_spi;
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.get_cpi.
+ */
+static status_t get_cpi(private_kernel_pfkey_ipsec_t *this,
+ host_t *src, host_t *dst,
+ u_int32_t reqid, u_int16_t *cpi)
+{
+ return FAILED;
+}
+
+/**
+ * Implementation of kernel_interface_t.add_sa.
+ */
+static status_t add_sa(private_kernel_pfkey_ipsec_t *this,
+ host_t *src, host_t *dst, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid,
+ u_int64_t expire_soft, u_int64_t expire_hard,
+ u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key,
+ ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool encap, bool inbound)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_sa *sa;
+ struct sadb_x_sa2 *sa2;
+ struct sadb_address *addr;
+ struct sadb_lifetime *lft;
+ struct sadb_key *key;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}", ntohl(spi), reqid);
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = inbound ? SADB_UPDATE : SADB_ADD;
+ msg->sadb_msg_satype = proto_ike2satype(protocol);
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_spi = spi;
+ sa->sadb_sa_replay = (protocol == IPPROTO_COMP) ? 0 : 32;
+ sa->sadb_sa_auth = lookup_algorithm(integrity_algs, int_alg);
+ sa->sadb_sa_encrypt = lookup_algorithm(encryption_algs, enc_alg);
+ PFKEY_EXT_ADD(msg, sa);
+
+ sa2 = (struct sadb_x_sa2*)PFKEY_EXT_ADD_NEXT(msg);
+ sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
+ sa2->sadb_x_sa2_len = PFKEY_LEN(sizeof(struct sadb_spirange));
+ sa2->sadb_x_sa2_mode = mode2kernel(mode);
+ sa2->sadb_x_sa2_reqid = reqid;
+ PFKEY_EXT_ADD(msg, sa2);
+
+ addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+ host2ext(src, addr);
+ PFKEY_EXT_ADD(msg, addr);
+
+ addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+ host2ext(dst, addr);
+ PFKEY_EXT_ADD(msg, addr);
+
+ lft = (struct sadb_lifetime*)PFKEY_EXT_ADD_NEXT(msg);
+ lft->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
+ lft->sadb_lifetime_len = PFKEY_LEN(sizeof(struct sadb_lifetime));
+ lft->sadb_lifetime_addtime = expire_soft;
+ PFKEY_EXT_ADD(msg, lft);
+
+ lft = (struct sadb_lifetime*)PFKEY_EXT_ADD_NEXT(msg);
+ lft->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
+ lft->sadb_lifetime_len = PFKEY_LEN(sizeof(struct sadb_lifetime));
+ lft->sadb_lifetime_addtime = expire_hard;
+ PFKEY_EXT_ADD(msg, lft);
+
+ if (enc_alg != ENCR_UNDEFINED)
+ {
+ if (!sa->sadb_sa_encrypt)
+ {
+ DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
+ encryption_algorithm_names, enc_alg);
+ return FAILED;
+ }
+ DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
+ encryption_algorithm_names, enc_alg, enc_key.len * 8);
+
+ key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg);
+ key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
+ key->sadb_key_bits = enc_key.len * 8;
+ key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + enc_key.len);
+ memcpy(key + 1, enc_key.ptr, enc_key.len);
+
+ PFKEY_EXT_ADD(msg, key);
+ }
+
+ if (int_alg != AUTH_UNDEFINED)
+ {
+ if (!sa->sadb_sa_auth)
+ {
+ DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
+ integrity_algorithm_names, int_alg);
+ return FAILED;
+ }
+ DBG2(DBG_KNL, " using integrity algorithm %N with key size %d",
+ integrity_algorithm_names, int_alg, int_key.len * 8);
+
+ key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg);
+ key->sadb_key_exttype = SADB_EXT_KEY_AUTH;
+ key->sadb_key_bits = int_key.len * 8;
+ key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + int_key.len);
+ memcpy(key + 1, int_key.ptr, int_key.len);
+
+ PFKEY_EXT_ADD(msg, key);
+ }
+
+ if (ipcomp != IPCOMP_NONE)
+ {
+ /*TODO*/
+ }
+
+ if (encap)
+ {
+ add_encap_ext(msg, src, dst);
+ }
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x: %s (%d)",
+ ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+
+ free(out);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.update_sa.
+ */
+static status_t update_sa(private_kernel_pfkey_ipsec_t *this,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
+ host_t *src, host_t *dst,
+ host_t *new_src, host_t *new_dst,
+ bool encap, bool new_encap)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_sa *sa;
+ struct sadb_address *addr;
+ pfkey_msg_t response;
+ size_t len;
+
+ /* we can't update the SA if any of the ip addresses have changed.
+ * that's because we can't use SADB_UPDATE and by deleting and readding the
+ * SA the sequence numbers would get lost */
+ if (!src->ip_equals(src, new_src) ||
+ !dst->ip_equals(dst, new_dst))
+ {
+ DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: address changes"
+ " are not supported", ntohl(spi));
+ return NOT_SUPPORTED;
+ }
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_GET;
+ msg->sadb_msg_satype = proto_ike2satype(protocol);
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_spi = spi;
+ PFKEY_EXT_ADD(msg, sa);
+
+ /* the kernel wants a SADB_EXT_ADDRESS_SRC to be present even though
+ * it is not used for anything, so we just send dst twice */
+ addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+ host2ext(dst, addr);
+ PFKEY_EXT_ADD(msg, addr);
+
+ addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+ host2ext(dst, addr);
+ PFKEY_EXT_ADD(msg, addr);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x",
+ ntohl(spi));
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x: %s (%d)",
+ ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ else if (parse_pfkey_message(out, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x: parsing response "
+ "from kernel failed", ntohl(spi));
+ free(out);
+ return FAILED;
+ }
+
+ DBG2(DBG_KNL, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H",
+ ntohl(spi), src, dst, new_src, new_dst);
+
+ memset(&request, 0, sizeof(request));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_UPDATE;
+ msg->sadb_msg_satype = proto_ike2satype(protocol);
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ PFKEY_EXT_COPY(msg, response.sa);
+ PFKEY_EXT_COPY(msg, response.x_sa2);
+
+ PFKEY_EXT_COPY(msg, response.src);
+ PFKEY_EXT_COPY(msg, response.dst);
+
+ PFKEY_EXT_COPY(msg, response.lft_soft);
+ PFKEY_EXT_COPY(msg, response.lft_hard);
+
+ if (response.key_encr)
+ {
+ PFKEY_EXT_COPY(msg, response.key_encr);
+ }
+
+ if (response.key_auth)
+ {
+ PFKEY_EXT_COPY(msg, response.key_auth);
+ }
+
+ if (new_encap)
+ {
+ add_encap_ext(msg, new_src, new_dst);
+ }
+
+ free(out);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: %s (%d)",
+ ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.del_sa.
+ */
+static status_t del_sa(private_kernel_pfkey_ipsec_t *this, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_sa *sa;
+ struct sadb_address *addr;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_DELETE;
+ msg->sadb_msg_satype = proto_ike2satype(protocol);
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+ sa->sadb_sa_exttype = SADB_EXT_SA;
+ sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
+ sa->sadb_sa_spi = spi;
+ PFKEY_EXT_ADD(msg, sa);
+
+ /* the kernel wants a SADB_EXT_ADDRESS_SRC to be present even though
+ * it is not used for anything, so we just send dst twice */
+ addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+ host2ext(dst, addr);
+ PFKEY_EXT_ADD(msg, addr);
+
+ addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+ host2ext(dst, addr);
+ PFKEY_EXT_ADD(msg, addr);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi));
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x: %s (%d)",
+ ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+
+ DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi));
+ free(out);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.add_policy.
+ */
+static status_t add_policy(private_kernel_pfkey_ipsec_t *this,
+ host_t *src, host_t *dst,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid,
+ ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool routed)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_x_policy *pol;
+ struct sadb_address *addr;
+ struct sadb_x_ipsecrequest *req;
+ policy_entry_t *policy, *found = NULL;
+ pfkey_msg_t response;
+ size_t len;
+
+ /* create a policy */
+ policy = create_policy_entry(src_ts, dst_ts, direction, reqid);
+
+ /* find a matching policy */
+ this->mutex->lock(this->mutex);
+ if (this->policies->find_first(this->policies,
+ (linked_list_match_t)policy_entry_equals, (void**)&found, policy) == SUCCESS)
+ {
+ /* use existing policy */
+ found->refcount++;
+ DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing "
+ "refcount", src_ts, dst_ts,
+ policy_dir_names, direction);
+ policy_entry_destroy(policy);
+ policy = found;
+ }
+ else
+ {
+ /* apply the new one, if we have no such policy */
+ this->policies->insert_last(this->policies, policy);
+ policy->refcount = 1;
+ }
+
+ memset(&request, 0, sizeof(request));
+
+ DBG2(DBG_KNL, "adding policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = found ? SADB_X_SPDUPDATE : SADB_X_SPDADD;
+ msg->sadb_msg_satype = 0;
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ pol = (struct sadb_x_policy*)PFKEY_EXT_ADD_NEXT(msg);
+ pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+ pol->sadb_x_policy_len = PFKEY_LEN(sizeof(struct sadb_x_policy));
+ pol->sadb_x_policy_id = 0;
+ pol->sadb_x_policy_dir = dir2kernel(direction);
+ /* calculate priority based on source selector size, small size = high prio */
+ pol->sadb_x_policy_priority = routed ? PRIO_LOW : PRIO_HIGH;
+ pol->sadb_x_policy_priority -= policy->src.mask * 10;
+ pol->sadb_x_policy_priority -= policy->src.proto != IPSEC_PROTO_ANY ? 2 : 0;
+ pol->sadb_x_policy_priority -= policy->src.net->get_port(policy->src.net) ? 1 : 0;
+ pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
+
+ /* one or more sadb_x_ipsecrequest extensions are added to the sadb_x_policy extension */
+ req = (struct sadb_x_ipsecrequest*)(pol + 1);
+ req->sadb_x_ipsecrequest_proto = proto_ike2ip(protocol);
+ /* !!! the length of this struct MUST be in octets instead of 64 bit words */
+ req->sadb_x_ipsecrequest_len = sizeof(struct sadb_x_ipsecrequest);
+ req->sadb_x_ipsecrequest_mode = mode2kernel(mode);
+ req->sadb_x_ipsecrequest_reqid = reqid;
+ req->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
+ if (mode == MODE_TUNNEL)
+ {
+ sockaddr_t *sa;
+ socklen_t sl;
+ sa = src->get_sockaddr(src);
+ sl = *src->get_sockaddr_len(src);
+ memcpy(req + 1, sa, sl);
+ sa = dst->get_sockaddr(dst);
+ memcpy((u_int8_t*)(req + 1) + sl, sa, sl);
+ req->sadb_x_ipsecrequest_len += sl * 2;
+ }
+
+ pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len);
+ PFKEY_EXT_ADD(msg, pol);
+
+ addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+ addr->sadb_address_proto = policy->src.proto;
+ addr->sadb_address_prefixlen = policy->src.mask;
+ host2ext(policy->src.net, addr);
+ PFKEY_EXT_ADD(msg, addr);
+
+ addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+ addr->sadb_address_proto = policy->dst.proto;
+ addr->sadb_address_prefixlen = policy->dst.mask;
+ host2ext(policy->dst.net, addr);
+ PFKEY_EXT_ADD(msg, addr);
+
+ this->mutex->unlock(this->mutex);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to add policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to add policy %R === %R %N: %s (%d)", src_ts, dst_ts,
+ policy_dir_names, direction,
+ strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ else if (parse_pfkey_message(out, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to add policy %R === %R %N: parsing response "
+ "from kernel failed", src_ts, dst_ts, policy_dir_names, direction);
+ free(out);
+ return FAILED;
+ }
+
+ this->mutex->lock(this->mutex);
+
+ /* we try to find the policy again and update the kernel index */
+ if (this->policies->find_last(this->policies, NULL, (void**)&policy) != SUCCESS)
+ {
+ DBG2(DBG_KNL, "unable to update index, the policy %R === %R %N is "
+ "already gone, ignoring", src_ts, dst_ts, policy_dir_names, direction);
+ this->mutex->unlock(this->mutex);
+ free(out);
+ return SUCCESS;
+ }
+ policy->index = response.x_policy->sadb_x_policy_id;
+ free(out);
+
+ /* install a route, if:
+ * - we are NOT updating a policy
+ * - this is a forward policy (to just get one for each child)
+ * - we are in tunnel mode
+ * - we are not using IPv6 (does not work correctly yet!)
+ * - routing is not disabled via strongswan.conf
+ */
+ if (policy->route == NULL && direction == POLICY_FWD &&
+ mode != MODE_TRANSPORT && src->get_family(src) != AF_INET6 &&
+ this->install_routes)
+ {
+ route_entry_t *route = malloc_thing(route_entry_t);
+
+ if (charon->kernel_interface->get_address_by_ts(charon->kernel_interface,
+ dst_ts, &route->src_ip) == SUCCESS)
+ {
+ /* get the nexthop to src (src as we are in POLICY_FWD).*/
+ route->gateway = charon->kernel_interface->get_nexthop(
+ charon->kernel_interface, src);
+ route->if_name = charon->kernel_interface->get_interface(
+ charon->kernel_interface, dst);
+ route->dst_net = chunk_clone(policy->src.net->get_address(policy->src.net));
+ route->prefixlen = policy->src.mask;
+
+ switch (charon->kernel_interface->add_route(charon->kernel_interface,
+ route->dst_net, route->prefixlen, route->gateway,
+ route->src_ip, route->if_name))
+ {
+ default:
+ DBG1(DBG_KNL, "unable to install source route for %H",
+ route->src_ip);
+ /* FALL */
+ case ALREADY_DONE:
+ /* route exists, do not uninstall */
+ route_entry_destroy(route);
+ break;
+ case SUCCESS:
+ /* cache the installed route */
+ policy->route = route;
+ break;
+ }
+ }
+ else
+ {
+ free(route);
+ }
+ }
+
+ this->mutex->unlock(this->mutex);
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.query_policy.
+ */
+static status_t query_policy(private_kernel_pfkey_ipsec_t *this,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, u_int32_t *use_time)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_x_policy *pol;
+ struct sadb_address *addr;
+ policy_entry_t *policy, *found = NULL;
+ pfkey_msg_t response;
+ size_t len;
+
+ DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+
+ /* create a policy */
+ policy = create_policy_entry(src_ts, dst_ts, direction, 0);
+
+ /* find a matching policy */
+ this->mutex->lock(this->mutex);
+ if (this->policies->find_first(this->policies,
+ (linked_list_match_t)policy_entry_equals, (void**)&found, policy) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "querying policy %R === %R %N failed, not found", src_ts,
+ dst_ts, policy_dir_names, direction);
+ policy_entry_destroy(policy);
+ this->mutex->unlock(this->mutex);
+ return NOT_FOUND;
+ }
+ policy_entry_destroy(policy);
+ policy = found;
+
+ memset(&request, 0, sizeof(request));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_X_SPDGET;
+ msg->sadb_msg_satype = 0;
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ pol = (struct sadb_x_policy*)PFKEY_EXT_ADD_NEXT(msg);
+ pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+ pol->sadb_x_policy_id = policy->index;
+ pol->sadb_x_policy_len = PFKEY_LEN(sizeof(struct sadb_x_policy));
+ pol->sadb_x_policy_dir = dir2kernel(direction);
+ pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
+ PFKEY_EXT_ADD(msg, pol);
+
+ addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+ addr->sadb_address_proto = policy->src.proto;
+ addr->sadb_address_prefixlen = policy->src.mask;
+ host2ext(policy->src.net, addr);
+ PFKEY_EXT_ADD(msg, addr);
+
+ addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+ addr->sadb_address_proto = policy->dst.proto;
+ addr->sadb_address_prefixlen = policy->dst.mask;
+ host2ext(policy->dst.net, addr);
+ PFKEY_EXT_ADD(msg, addr);
+
+ this->mutex->unlock(this->mutex);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to query policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to query policy %R === %R %N: %s (%d)", src_ts,
+ dst_ts, policy_dir_names, direction,
+ strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ else if (parse_pfkey_message(out, &response) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to query policy %R === %R %N: parsing response "
+ "from kernel failed", src_ts, dst_ts, policy_dir_names, direction);
+ free(out);
+ return FAILED;
+ }
+
+ *use_time = response.lft_current->sadb_lifetime_usetime;
+
+ free(out);
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.del_policy.
+ */
+static status_t del_policy(private_kernel_pfkey_ipsec_t *this,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, bool unrouted)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ struct sadb_x_policy *pol;
+ struct sadb_address *addr;
+ policy_entry_t *policy, *found = NULL;
+ route_entry_t *route;
+ size_t len;
+
+ DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+
+ /* create a policy */
+ policy = create_policy_entry(src_ts, dst_ts, direction, 0);
+
+ /* find a matching policy */
+ this->mutex->lock(this->mutex);
+ if (this->policies->find_first(this->policies,
+ (linked_list_match_t)policy_entry_equals, (void**)&found, policy) == SUCCESS)
+ {
+ if (--found->refcount > 0)
+ {
+ /* is used by more SAs, keep in kernel */
+ DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
+ policy_entry_destroy(policy);
+ this->mutex->unlock(this->mutex);
+ return SUCCESS;
+ }
+ /* remove if last reference */
+ this->policies->remove(this->policies, found, NULL);
+ policy_entry_destroy(policy);
+ policy = found;
+ }
+ else
+ {
+ DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts,
+ dst_ts, policy_dir_names, direction);
+ policy_entry_destroy(policy);
+ this->mutex->unlock(this->mutex);
+ return NOT_FOUND;
+ }
+ this->mutex->unlock(this->mutex);
+
+ memset(&request, 0, sizeof(request));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_X_SPDDELETE;
+ msg->sadb_msg_satype = 0;
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ pol = (struct sadb_x_policy*)PFKEY_EXT_ADD_NEXT(msg);
+ pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+ pol->sadb_x_policy_len = PFKEY_LEN(sizeof(struct sadb_x_policy));
+ pol->sadb_x_policy_dir = dir2kernel(direction);
+ pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
+ PFKEY_EXT_ADD(msg, pol);
+
+ addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+ addr->sadb_address_proto = policy->src.proto;
+ addr->sadb_address_prefixlen = policy->src.mask;
+ host2ext(policy->src.net, addr);
+ PFKEY_EXT_ADD(msg, addr);
+
+ addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+ addr->sadb_address_proto = policy->dst.proto;
+ addr->sadb_address_prefixlen = policy->dst.mask;
+ host2ext(policy->dst.net, addr);
+ PFKEY_EXT_ADD(msg, addr);
+
+ route = policy->route;
+ policy->route = NULL;
+ policy_entry_destroy(policy);
+
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to delete policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to delete policy %R === %R %N: %s (%d)", src_ts,
+ dst_ts, policy_dir_names, direction,
+ strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+
+ if (route)
+ {
+ if (charon->kernel_interface->del_route(charon->kernel_interface,
+ route->dst_net, route->prefixlen, route->gateway,
+ route->src_ip, route->if_name) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "error uninstalling route installed with "
+ "policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ }
+ route_entry_destroy(route);
+ }
+
+ return SUCCESS;
+}
+
+/**
+ * Register a socket for AQUIRE/EXPIRE messages
+ */
+static status_t register_pfkey_socket(private_kernel_pfkey_ipsec_t *this, u_int8_t satype)
+{
+ unsigned char request[PFKEY_BUFFER_SIZE];
+ struct sadb_msg *msg, *out;
+ size_t len;
+
+ memset(&request, 0, sizeof(request));
+
+ msg = (struct sadb_msg*)request;
+ msg->sadb_msg_version = PF_KEY_V2;
+ msg->sadb_msg_type = SADB_REGISTER;
+ msg->sadb_msg_satype = satype;
+ msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+ if (pfkey_send_socket(this, this->socket_events, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to register PF_KEY socket");
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to register PF_KEY socket: %s (%d)",
+ strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
+ free(out);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.destroy.
+ */
+static void destroy(private_kernel_pfkey_ipsec_t *this)
+{
+ this->job->cancel(this->job);
+ close(this->socket);
+ close(this->socket_events);
+ this->policies->destroy_function(this->policies, (void*)policy_entry_destroy);
+ this->mutex->destroy(this->mutex);
+ this->mutex_pfkey->destroy(this->mutex_pfkey);
+ free(this);
+}
+
+/**
+ * Add bypass policies for IKE on the sockets of charon
+ */
+static bool add_bypass_policies(private_kernel_pfkey_ipsec_t *this)
+{
+ int fd, family, port;
+ enumerator_t *sockets;
+ bool status = TRUE;
+
+ sockets = charon->socket->create_enumerator(charon->socket);
+ while (sockets->enumerate(sockets, &fd, &family, &port))
+ {
+ struct sadb_x_policy policy;
+ u_int sol, ipsec_policy;
+
+ switch (family)
+ {
+ case AF_INET:
+ sol = SOL_IP;
+ ipsec_policy = IP_IPSEC_POLICY;
+ break;
+ case AF_INET6:
+ {
+ sol = SOL_IPV6;
+ ipsec_policy = IPV6_IPSEC_POLICY;
+ break;
+ }
+ }
+
+ memset(&policy, 0, sizeof(policy));
+ policy.sadb_x_policy_len = sizeof(policy) / sizeof(u_int64_t);
+ policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+ policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS;
+
+ policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
+ if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
+ {
+ DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
+ strerror(errno));
+ status = FALSE;
+ break;
+ }
+ policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
+ if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
+ {
+ DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
+ strerror(errno));
+ status = FALSE;
+ break;
+ }
+ }
+ sockets->destroy(sockets);
+ return status;
+}
+
+/*
+ * Described in header.
+ */
+kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create()
+{
+ private_kernel_pfkey_ipsec_t *this = malloc_thing(private_kernel_pfkey_ipsec_t);
+
+ /* public functions */
+ this->public.interface.get_spi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
+ this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
+ this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool))add_sa;
+ this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,u_int16_t,host_t*,host_t*,host_t*,host_t*,bool,bool))update_sa;
+ this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,u_int32_t,protocol_id_t,u_int16_t))del_sa;
+ this->public.interface.add_policy = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t,protocol_id_t,u_int32_t,ipsec_mode_t,u_int16_t,u_int16_t,bool))add_policy;
+ this->public.interface.query_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
+ this->public.interface.del_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,bool))del_policy;
+
+ this->public.interface.destroy = (void(*)(kernel_ipsec_t*)) destroy;
+
+ /* private members */
+ this->policies = linked_list_create();
+ this->mutex = mutex_create(MUTEX_DEFAULT);
+ this->mutex_pfkey = mutex_create(MUTEX_DEFAULT);
+ this->install_routes = lib->settings->get_bool(lib->settings,
+ "charon.install_routes", TRUE);
+ this->seq = 0;
+
+ /* create a PF_KEY socket to communicate with the kernel */
+ this->socket = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
+ if (this->socket <= 0)
+ {
+ charon->kill(charon, "unable to create PF_KEY socket");
+ }
+
+ /* create a PF_KEY socket for ACQUIRE & EXPIRE */
+ this->socket_events = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
+ if (this->socket_events <= 0)
+ {
+ charon->kill(charon, "unable to create PF_KEY event socket");
+ }
+
+ /* add bypass policies on the sockets used by charon */
+ if (!add_bypass_policies(this))
+ {
+ charon->kill(charon, "unable to add bypass policies on sockets");
+ }
+
+ /* register the event socket */
+ if (register_pfkey_socket(this, SADB_SATYPE_ESP) != SUCCESS ||
+ register_pfkey_socket(this, SADB_SATYPE_AH) != SUCCESS)
+ {
+ charon->kill(charon, "unable to register PF_KEY event socket");
+ }
+
+ this->job = callback_job_create((callback_job_cb_t)receive_events,
+ this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+
+ return &this->public;
+}
diff --git a/src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.h b/src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.h
new file mode 100644
index 000000000..6e2ec5377
--- /dev/null
+++ b/src/charon/plugins/kernel_pfkey/kernel_pfkey_ipsec.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * 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: kernel_pfkey_ipsec.h 4361 2008-10-01 16:47:51Z tobias $
+ */
+
+/**
+ * @defgroup kernel_pfkey_ipsec_i kernel_pfkey_ipsec
+ * @{ @ingroup kernel_pfkey
+ */
+
+#ifndef KERNEL_PFKEY_IPSEC_H_
+#define KERNEL_PFKEY_IPSEC_H_
+
+#include <kernel/kernel_ipsec.h>
+
+typedef struct kernel_pfkey_ipsec_t kernel_pfkey_ipsec_t;
+
+/**
+ * Implementation of the kernel ipsec interface using PF_KEY.
+ */
+struct kernel_pfkey_ipsec_t {
+
+ /**
+ * Implements kernel_ipsec_t interface
+ */
+ kernel_ipsec_t interface;
+};
+
+/**
+ * Create a PF_KEY kernel ipsec interface instance.
+ *
+ * @return kernel_pfkey_ipsec_t instance
+ */
+kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create();
+
+#endif /* KERNEL_PFKEY_IPSEC_H_ @} */
diff --git a/src/charon/plugins/kernel_pfkey/kernel_pfkey_plugin.c b/src/charon/plugins/kernel_pfkey/kernel_pfkey_plugin.c
new file mode 100644
index 000000000..93015d75a
--- /dev/null
+++ b/src/charon/plugins/kernel_pfkey/kernel_pfkey_plugin.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * 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: kernel_pfkey_plugin.c 4361 2008-10-01 16:47:51Z tobias $
+ */
+
+
+#include "kernel_pfkey_plugin.h"
+
+#include "kernel_pfkey_ipsec.h"
+
+#include <daemon.h>
+
+typedef struct private_kernel_pfkey_plugin_t private_kernel_pfkey_plugin_t;
+
+/**
+ * private data of kernel PF_KEY plugin
+ */
+struct private_kernel_pfkey_plugin_t {
+ /**
+ * implements plugin interface
+ */
+ kernel_pfkey_plugin_t public;
+};
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_kernel_pfkey_plugin_t *this)
+{
+ charon->kernel_interface->remove_ipsec_interface(charon->kernel_interface, (kernel_ipsec_constructor_t)kernel_pfkey_ipsec_create);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *plugin_create()
+{
+ private_kernel_pfkey_plugin_t *this = malloc_thing(private_kernel_pfkey_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ charon->kernel_interface->add_ipsec_interface(charon->kernel_interface, (kernel_ipsec_constructor_t)kernel_pfkey_ipsec_create);
+
+ return &this->public.plugin;
+}
diff --git a/src/charon/plugins/kernel_pfkey/kernel_pfkey_plugin.h b/src/charon/plugins/kernel_pfkey/kernel_pfkey_plugin.h
new file mode 100644
index 000000000..5e256ca74
--- /dev/null
+++ b/src/charon/plugins/kernel_pfkey/kernel_pfkey_plugin.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008 Tobias Brunner
+ * 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: kernel_pfkey_plugin.h 4361 2008-10-01 16:47:51Z tobias $
+ */
+
+/**
+ * @defgroup kernel_pfkey kernel_pfkey
+ * @ingroup cplugins
+ *
+ * @defgroup kernel_pfkey_plugin kernel_pfkey_plugin
+ * @{ @ingroup kernel_pfkey
+ */
+
+#ifndef KERNEL_PFKEY_PLUGIN_H_
+#define KERNEL_PFKEY_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct kernel_pfkey_plugin_t kernel_pfkey_plugin_t;
+
+/**
+ * PF_KEY kernel interface plugin
+ */
+struct kernel_pfkey_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+/**
+ * Create a kernel_pfkey_plugin instance.
+ */
+plugin_t *plugin_create();
+
+#endif /* KERNEL_PFKEY_PLUGIN_H_ @} */
diff --git a/src/charon/plugins/load_tester/Makefile.am b/src/charon/plugins/load_tester/Makefile.am
new file mode 100644
index 000000000..88a6b688c
--- /dev/null
+++ b/src/charon/plugins/load_tester/Makefile.am
@@ -0,0 +1,16 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
+
+AM_CFLAGS = -rdynamic
+
+plugin_LTLIBRARIES = libstrongswan-load-tester.la
+
+libstrongswan_load_tester_la_SOURCES = \
+ load_tester_plugin.c load_tester_plugin.h \
+ load_tester_config.c load_tester_config.h \
+ load_tester_creds.c load_tester_creds.h \
+ load_tester_ipsec.c load_tester_ipsec.h \
+ load_tester_listener.c load_tester_listener.h
+
+libstrongswan_load_tester_la_LDFLAGS = -module
+
diff --git a/src/charon/plugins/load_tester/Makefile.in b/src/charon/plugins/load_tester/Makefile.in
new file mode 100644
index 000000000..a0a749b87
--- /dev/null
+++ b/src/charon/plugins/load_tester/Makefile.in
@@ -0,0 +1,509 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/charon/plugins/load_tester
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(plugindir)"
+pluginLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+libstrongswan_load_tester_la_LIBADD =
+am_libstrongswan_load_tester_la_OBJECTS = load_tester_plugin.lo \
+ load_tester_config.lo load_tester_creds.lo \
+ load_tester_ipsec.lo load_tester_listener.lo
+libstrongswan_load_tester_la_OBJECTS = \
+ $(am_libstrongswan_load_tester_la_OBJECTS)
+libstrongswan_load_tester_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_load_tester_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_load_tester_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_load_tester_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@
+IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LINUX_HEADERS = @LINUX_HEADERS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+confdir = @confdir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libstrongswan_plugins = @libstrongswan_plugins@
+linuxdir = @linuxdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+resolv_conf = @resolv_conf@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+simreader = @simreader@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
+AM_CFLAGS = -rdynamic
+plugin_LTLIBRARIES = libstrongswan-load-tester.la
+libstrongswan_load_tester_la_SOURCES = \
+ load_tester_plugin.c load_tester_plugin.h \
+ load_tester_config.c load_tester_config.h \
+ load_tester_creds.c load_tester_creds.h \
+ load_tester_ipsec.c load_tester_ipsec.h \
+ load_tester_listener.c load_tester_listener.h
+
+libstrongswan_load_tester_la_LDFLAGS = -module
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/load_tester/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/charon/plugins/load_tester/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-load-tester.la: $(libstrongswan_load_tester_la_OBJECTS) $(libstrongswan_load_tester_la_DEPENDENCIES)
+ $(libstrongswan_load_tester_la_LINK) -rpath $(plugindir) $(libstrongswan_load_tester_la_OBJECTS) $(libstrongswan_load_tester_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_tester_config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_tester_creds.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_tester_ipsec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_tester_listener.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_tester_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+
+# 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/charon/plugins/load_tester/load_tester_config.c b/src/charon/plugins/load_tester/load_tester_config.c
new file mode 100644
index 000000000..8e93d24bb
--- /dev/null
+++ b/src/charon/plugins/load_tester/load_tester_config.c
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#include "load_tester_config.h"
+
+#include <daemon.h>
+
+typedef struct private_load_tester_config_t private_load_tester_config_t;
+
+/**
+ * Private data of an load_tester_config_t object
+ */
+struct private_load_tester_config_t {
+
+ /**
+ * Public part
+ */
+ load_tester_config_t public;
+
+ /**
+ * peer config
+ */
+ peer_cfg_t *peer_cfg;
+};
+
+/**
+ * Implementation of backend_t.create_peer_cfg_enumerator.
+ */
+static enumerator_t* create_peer_cfg_enumerator(private_load_tester_config_t *this,
+ identification_t *me,
+ identification_t *other)
+{
+ return enumerator_create_single(this->peer_cfg, NULL);
+}
+
+/**
+ * Implementation of backend_t.create_ike_cfg_enumerator.
+ */
+static enumerator_t* create_ike_cfg_enumerator(private_load_tester_config_t *this,
+ host_t *me, host_t *other)
+{
+ ike_cfg_t *ike_cfg;
+
+ ike_cfg = this->peer_cfg->get_ike_cfg(this->peer_cfg);
+ return enumerator_create_single(ike_cfg, NULL);
+}
+
+/**
+ * implements backend_t.get_peer_cfg_by_name.
+ */
+static peer_cfg_t *get_peer_cfg_by_name(private_load_tester_config_t *this,
+ char *name)
+{
+ if (streq(name, "load-test"))
+ {
+ return this->peer_cfg->get_ref(this->peer_cfg);;
+ }
+ return NULL;
+}
+
+/**
+ * Implementation of load_tester_config_t.destroy.
+ */
+static void destroy(private_load_tester_config_t *this)
+{
+ this->peer_cfg->destroy(this->peer_cfg);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+load_tester_config_t *load_tester_config_create()
+{
+ private_load_tester_config_t *this = malloc_thing(private_load_tester_config_t);
+ ike_cfg_t *ike_cfg;
+ child_cfg_t *child_cfg;
+ proposal_t *proposal;
+ traffic_selector_t *ts;
+ auth_info_t *auth;
+ auth_class_t class;
+ char *remote, *pool;
+ host_t *vip = NULL;
+
+ this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator;
+ this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator;
+ this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name;
+ this->public.destroy = (void(*)(load_tester_config_t*))destroy;
+
+ if (lib->settings->get_bool(lib->settings,
+ "charon.plugins.load_tester.request_virtual_ip", FALSE))
+ {
+ vip = host_create_from_string("0.0.0.0", 0);
+ }
+ pool = lib->settings->get_str(lib->settings,
+ "charon.plugins.load_tester.pool", NULL);
+ remote = lib->settings->get_str(lib->settings,
+ "charon.plugins.load_tester.remote", "127.0.0.1");
+ ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", remote);
+ proposal = proposal_create_from_string(PROTO_IKE,
+ lib->settings->get_str(lib->settings,
+ "charon.plugins.load_tester.proposal", "aes128-sha1-modp768"));
+ if (!proposal)
+ { /* fallback */
+ proposal = proposal_create_from_string(PROTO_IKE, "aes128-sha1-modp768");
+ }
+ ike_cfg->add_proposal(ike_cfg, proposal);
+ this->peer_cfg = peer_cfg_create("load-test", 2, ike_cfg,
+ identification_create_from_string("load-test@strongswan.org"),
+ identification_create_from_string("load-test@strongswan.org"),
+ CERT_SEND_IF_ASKED, UNIQUE_NO, 1, 0, 0, /* keytries, rekey, reauth */
+ 0, 0, TRUE, 60, /* jitter, overtime, mobike, dpddelay */
+ vip, pool, FALSE, NULL, NULL);
+ auth = this->peer_cfg->get_auth(this->peer_cfg);
+ class = AUTH_CLASS_PUBKEY;
+ auth->add_item(auth, AUTHN_AUTH_CLASS, &class);
+ child_cfg = child_cfg_create("load-test", 600, 400, 100, NULL, TRUE,
+ MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE);
+ proposal = proposal_create_from_string(PROTO_ESP, "aes128-sha1");
+ child_cfg->add_proposal(child_cfg, proposal);
+ ts = traffic_selector_create_dynamic(0, 0, 65535);
+ child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
+ ts = traffic_selector_create_dynamic(0, 0, 65535);
+ child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
+ this->peer_cfg->add_child_cfg(this->peer_cfg, child_cfg);
+
+ return &this->public;
+}
+
diff --git a/src/charon/plugins/load_tester/load_tester_config.h b/src/charon/plugins/load_tester/load_tester_config.h
new file mode 100644
index 000000000..d5391da63
--- /dev/null
+++ b/src/charon/plugins/load_tester/load_tester_config.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+/**
+ * @defgroup load_tester_config_t load_tester_config
+ * @{ @ingroup load_tester
+ */
+
+#ifndef LOAD_TESTER_CONFIG_H_
+#define LOAD_TESTER_CONFIG_H_
+
+#include <config/backend.h>
+
+typedef struct load_tester_config_t load_tester_config_t;
+
+/**
+ * Provide configurations for load testing.
+ */
+struct load_tester_config_t {
+
+ /**
+ * Implements backend_t interface
+ */
+ backend_t backend;
+
+ /**
+ * Destroy the backend.
+ */
+ void (*destroy)(load_tester_config_t *this);
+};
+
+/**
+ * Create a configuration backend for load testing.
+ *
+ * @return configuration backend
+ */
+load_tester_config_t *load_tester_config_create();
+
+#endif /* LOAD_TESTER_CONFIG_H_ @}*/
diff --git a/src/charon/plugins/load_tester/load_tester_creds.c b/src/charon/plugins/load_tester/load_tester_creds.c
new file mode 100644
index 000000000..ec69a1ac9
--- /dev/null
+++ b/src/charon/plugins/load_tester/load_tester_creds.c
@@ -0,0 +1,236 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#include "load_tester_creds.h"
+
+#include <daemon.h>
+#include <credentials/keys/shared_key.h>
+#include <utils/identification.h>
+
+typedef struct private_load_tester_creds_t private_load_tester_creds_t;
+
+/**
+ * Private data of an load_tester_creds_t object
+ */
+struct private_load_tester_creds_t {
+ /**
+ * Public part
+ */
+ load_tester_creds_t public;
+
+ /**
+ * Private key to create signatures
+ */
+ private_key_t *private;
+
+ /**
+ * Trusted certificate to verify signatures
+ */
+ certificate_t *cert;
+};
+
+/**
+ * 1024-bit RSA key:
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDQXr7poAPYZLxmTCqR51STGRuk9Hc5SWtTcs6b2RzpnP8EVRLx
+JEVxOKE9Mw6n7mD1pNrupCpnpGRdLAV5VznTPhSQ6k7ppJJrxosRYg0pHTZqBUEC
+7nQFwAe10g8q0UnM1wa4lJzGxDH78d21cVweJgbkxAeyriS0jhNs7gO5nQIDAQAB
+AoGACVACtkxJf7VY2jWTPXwaQoy/uIqYfX3zhwI9i6eTbDlxCE+JDi/xzpKaWjLa
+99RmjvP0OPArWQB239ck03x7gAm2obutosGbqbKzJZS5cyIayzyW9djZDHBdt9Ho
+quKB39aspWit3xPzkrr+QeIkiggtmBKALTBxTwxAU+P6euECQQD4IPdrzKbCrO79
+LKvoPrQQtTjL6ogag9rI9n2ZuoK3/XVybh2byOXT8tA5G5jSz9Ac8XeVOsnH9gT5
+3WXeaLOFAkEA1vrm/hVSEasp5eATgQ7ig9CF+GGKqhTwXp/uOSl/h3IRmStu5J0C
+9AkYyx0bn3j5R8iUEX/C00KSE1kQNh4NOQJAVOsLYlRG2idPH0xThQc4nuM2jes1
+K0Xm8ZISSDNhm1BeCoyPC4rExTW7d1/vfG5svgsRrvvQpOOYrl7MB0Lz9QJBALhg
+AWJiyLsskEd90Vx7dpvUaEHo7jMGuEx/X6GYzK5Oj3dNP9NEMfc4IhJ5SWqRJ0KA
+bTVA3MexLXT4iqXPSkkCQQDSjLhBwvEnSuW4ElIMzBwLbu7573z2gzU82Mj6trrw
+Osoox/vmcepT1Wjy4AvPZHgxp7vEXNSeS+M5L29QNTp8
+-----END RSA PRIVATE KEY-----
+ */
+static char private[] = {
+ 0x30,0x82,0x02,0x5d,0x02,0x01,0x00,0x02,0x81,0x81,0x00,0xd0,0x5e,0xbe,0xe9,0xa0,
+ 0x03,0xd8,0x64,0xbc,0x66,0x4c,0x2a,0x91,0xe7,0x54,0x93,0x19,0x1b,0xa4,0xf4,0x77,
+ 0x39,0x49,0x6b,0x53,0x72,0xce,0x9b,0xd9,0x1c,0xe9,0x9c,0xff,0x04,0x55,0x12,0xf1,
+ 0x24,0x45,0x71,0x38,0xa1,0x3d,0x33,0x0e,0xa7,0xee,0x60,0xf5,0xa4,0xda,0xee,0xa4,
+ 0x2a,0x67,0xa4,0x64,0x5d,0x2c,0x05,0x79,0x57,0x39,0xd3,0x3e,0x14,0x90,0xea,0x4e,
+ 0xe9,0xa4,0x92,0x6b,0xc6,0x8b,0x11,0x62,0x0d,0x29,0x1d,0x36,0x6a,0x05,0x41,0x02,
+ 0xee,0x74,0x05,0xc0,0x07,0xb5,0xd2,0x0f,0x2a,0xd1,0x49,0xcc,0xd7,0x06,0xb8,0x94,
+ 0x9c,0xc6,0xc4,0x31,0xfb,0xf1,0xdd,0xb5,0x71,0x5c,0x1e,0x26,0x06,0xe4,0xc4,0x07,
+ 0xb2,0xae,0x24,0xb4,0x8e,0x13,0x6c,0xee,0x03,0xb9,0x9d,0x02,0x03,0x01,0x00,0x01,
+ 0x02,0x81,0x80,0x09,0x50,0x02,0xb6,0x4c,0x49,0x7f,0xb5,0x58,0xda,0x35,0x93,0x3d,
+ 0x7c,0x1a,0x42,0x8c,0xbf,0xb8,0x8a,0x98,0x7d,0x7d,0xf3,0x87,0x02,0x3d,0x8b,0xa7,
+ 0x93,0x6c,0x39,0x71,0x08,0x4f,0x89,0x0e,0x2f,0xf1,0xce,0x92,0x9a,0x5a,0x32,0xda,
+ 0xf7,0xd4,0x66,0x8e,0xf3,0xf4,0x38,0xf0,0x2b,0x59,0x00,0x76,0xdf,0xd7,0x24,0xd3,
+ 0x7c,0x7b,0x80,0x09,0xb6,0xa1,0xbb,0xad,0xa2,0xc1,0x9b,0xa9,0xb2,0xb3,0x25,0x94,
+ 0xb9,0x73,0x22,0x1a,0xcb,0x3c,0x96,0xf5,0xd8,0xd9,0x0c,0x70,0x5d,0xb7,0xd1,0xe8,
+ 0xaa,0xe2,0x81,0xdf,0xd6,0xac,0xa5,0x68,0xad,0xdf,0x13,0xf3,0x92,0xba,0xfe,0x41,
+ 0xe2,0x24,0x8a,0x08,0x2d,0x98,0x12,0x80,0x2d,0x30,0x71,0x4f,0x0c,0x40,0x53,0xe3,
+ 0xfa,0x7a,0xe1,0x02,0x41,0x00,0xf8,0x20,0xf7,0x6b,0xcc,0xa6,0xc2,0xac,0xee,0xfd,
+ 0x2c,0xab,0xe8,0x3e,0xb4,0x10,0xb5,0x38,0xcb,0xea,0x88,0x1a,0x83,0xda,0xc8,0xf6,
+ 0x7d,0x99,0xba,0x82,0xb7,0xfd,0x75,0x72,0x6e,0x1d,0x9b,0xc8,0xe5,0xd3,0xf2,0xd0,
+ 0x39,0x1b,0x98,0xd2,0xcf,0xd0,0x1c,0xf1,0x77,0x95,0x3a,0xc9,0xc7,0xf6,0x04,0xf9,
+ 0xdd,0x65,0xde,0x68,0xb3,0x85,0x02,0x41,0x00,0xd6,0xfa,0xe6,0xfe,0x15,0x52,0x11,
+ 0xab,0x29,0xe5,0xe0,0x13,0x81,0x0e,0xe2,0x83,0xd0,0x85,0xf8,0x61,0x8a,0xaa,0x14,
+ 0xf0,0x5e,0x9f,0xee,0x39,0x29,0x7f,0x87,0x72,0x11,0x99,0x2b,0x6e,0xe4,0x9d,0x02,
+ 0xf4,0x09,0x18,0xcb,0x1d,0x1b,0x9f,0x78,0xf9,0x47,0xc8,0x94,0x11,0x7f,0xc2,0xd3,
+ 0x42,0x92,0x13,0x59,0x10,0x36,0x1e,0x0d,0x39,0x02,0x40,0x54,0xeb,0x0b,0x62,0x54,
+ 0x46,0xda,0x27,0x4f,0x1f,0x4c,0x53,0x85,0x07,0x38,0x9e,0xe3,0x36,0x8d,0xeb,0x35,
+ 0x2b,0x45,0xe6,0xf1,0x92,0x12,0x48,0x33,0x61,0x9b,0x50,0x5e,0x0a,0x8c,0x8f,0x0b,
+ 0x8a,0xc4,0xc5,0x35,0xbb,0x77,0x5f,0xef,0x7c,0x6e,0x6c,0xbe,0x0b,0x11,0xae,0xfb,
+ 0xd0,0xa4,0xe3,0x98,0xae,0x5e,0xcc,0x07,0x42,0xf3,0xf5,0x02,0x41,0x00,0xb8,0x60,
+ 0x01,0x62,0x62,0xc8,0xbb,0x2c,0x90,0x47,0x7d,0xd1,0x5c,0x7b,0x76,0x9b,0xd4,0x68,
+ 0x41,0xe8,0xee,0x33,0x06,0xb8,0x4c,0x7f,0x5f,0xa1,0x98,0xcc,0xae,0x4e,0x8f,0x77,
+ 0x4d,0x3f,0xd3,0x44,0x31,0xf7,0x38,0x22,0x12,0x79,0x49,0x6a,0x91,0x27,0x42,0x80,
+ 0x6d,0x35,0x40,0xdc,0xc7,0xb1,0x2d,0x74,0xf8,0x8a,0xa5,0xcf,0x4a,0x49,0x02,0x41,
+ 0x00,0xd2,0x8c,0xb8,0x41,0xc2,0xf1,0x27,0x4a,0xe5,0xb8,0x12,0x52,0x0c,0xcc,0x1c,
+ 0x0b,0x6e,0xee,0xf9,0xef,0x7c,0xf6,0x83,0x35,0x3c,0xd8,0xc8,0xfa,0xb6,0xba,0xf0,
+ 0x3a,0xca,0x28,0xc7,0xfb,0xe6,0x71,0xea,0x53,0xd5,0x68,0xf2,0xe0,0x0b,0xcf,0x64,
+ 0x78,0x31,0xa7,0xbb,0xc4,0x5c,0xd4,0x9e,0x4b,0xe3,0x39,0x2f,0x6f,0x50,0x35,0x3a,
+ 0x7c,
+};
+
+/**
+ * And an associated self-signed certificate
+-----BEGIN CERTIFICATE-----
+MIIB2zCCAUSgAwIBAgIRAKmSLQc+3QV4WswVkpxqY5kwDQYJKoZIhvcNAQEFBQAw
+FzEVMBMGA1UEAxMMbG9hZC10ZXN0aW5nMB4XDTA4MTAyMTEyNDk0MFoXDTEzMTAy
+MDEyNDk0MFowFzEVMBMGA1UEAxMMbG9hZC10ZXN0aW5nMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQDQXr7poAPYZLxmTCqR51STGRuk9Hc5SWtTcs6b2RzpnP8E
+VRLxJEVxOKE9Mw6n7mD1pNrupCpnpGRdLAV5VznTPhSQ6k7ppJJrxosRYg0pHTZq
+BUEC7nQFwAe10g8q0UnM1wa4lJzGxDH78d21cVweJgbkxAeyriS0jhNs7gO5nQID
+AQABoycwJTAjBgNVHREEHDAagRhsb2FkLXRlc3RAc3Ryb25nc3dhbi5vcmcwDQYJ
+KoZIhvcNAQEFBQADgYEATyQ3KLVU13Q3U3uZZtQL56rm680wMLu0+2z164PnxcTu
+Donp19AwPfvl4y0kjCdQYqUA6NXczub40ZrCMfmZEbVarW9oAys9lWef8sqfW0pv
+asNWsTOOwgg4gcASh1VCYsMX73C8R1pegWM/btyX2SEa7+R1rBEZwHVtIxgFcnM=
+-----END CERTIFICATE-----
+ */
+static char cert[] = {
+ 0x30,0x82,0x01,0xdb,0x30,0x82,0x01,0x44,0xa0,0x03,0x02,0x01,0x02,0x02,0x11,0x00,
+ 0xa9,0x92,0x2d,0x07,0x3e,0xdd,0x05,0x78,0x5a,0xcc,0x15,0x92,0x9c,0x6a,0x63,0x99,
+ 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,
+ 0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x03,0x13,0x0c,0x6c,0x6f,0x61,0x64,
+ 0x2d,0x74,0x65,0x73,0x74,0x69,0x6e,0x67,0x30,0x1e,0x17,0x0d,0x30,0x38,0x31,0x30,
+ 0x32,0x31,0x31,0x32,0x34,0x39,0x34,0x30,0x5a,0x17,0x0d,0x31,0x33,0x31,0x30,0x32,
+ 0x30,0x31,0x32,0x34,0x39,0x34,0x30,0x5a,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,
+ 0x55,0x04,0x03,0x13,0x0c,0x6c,0x6f,0x61,0x64,0x2d,0x74,0x65,0x73,0x74,0x69,0x6e,
+ 0x67,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
+ 0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xd0,0x5e,
+ 0xbe,0xe9,0xa0,0x03,0xd8,0x64,0xbc,0x66,0x4c,0x2a,0x91,0xe7,0x54,0x93,0x19,0x1b,
+ 0xa4,0xf4,0x77,0x39,0x49,0x6b,0x53,0x72,0xce,0x9b,0xd9,0x1c,0xe9,0x9c,0xff,0x04,
+ 0x55,0x12,0xf1,0x24,0x45,0x71,0x38,0xa1,0x3d,0x33,0x0e,0xa7,0xee,0x60,0xf5,0xa4,
+ 0xda,0xee,0xa4,0x2a,0x67,0xa4,0x64,0x5d,0x2c,0x05,0x79,0x57,0x39,0xd3,0x3e,0x14,
+ 0x90,0xea,0x4e,0xe9,0xa4,0x92,0x6b,0xc6,0x8b,0x11,0x62,0x0d,0x29,0x1d,0x36,0x6a,
+ 0x05,0x41,0x02,0xee,0x74,0x05,0xc0,0x07,0xb5,0xd2,0x0f,0x2a,0xd1,0x49,0xcc,0xd7,
+ 0x06,0xb8,0x94,0x9c,0xc6,0xc4,0x31,0xfb,0xf1,0xdd,0xb5,0x71,0x5c,0x1e,0x26,0x06,
+ 0xe4,0xc4,0x07,0xb2,0xae,0x24,0xb4,0x8e,0x13,0x6c,0xee,0x03,0xb9,0x9d,0x02,0x03,
+ 0x01,0x00,0x01,0xa3,0x27,0x30,0x25,0x30,0x23,0x06,0x03,0x55,0x1d,0x11,0x04,0x1c,
+ 0x30,0x1a,0x81,0x18,0x6c,0x6f,0x61,0x64,0x2d,0x74,0x65,0x73,0x74,0x40,0x73,0x74,
+ 0x72,0x6f,0x6e,0x67,0x73,0x77,0x61,0x6e,0x2e,0x6f,0x72,0x67,0x30,0x0d,0x06,0x09,
+ 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x4f,
+ 0x24,0x37,0x28,0xb5,0x54,0xd7,0x74,0x37,0x53,0x7b,0x99,0x66,0xd4,0x0b,0xe7,0xaa,
+ 0xe6,0xeb,0xcd,0x30,0x30,0xbb,0xb4,0xfb,0x6c,0xf5,0xeb,0x83,0xe7,0xc5,0xc4,0xee,
+ 0x0e,0x89,0xe9,0xd7,0xd0,0x30,0x3d,0xfb,0xe5,0xe3,0x2d,0x24,0x8c,0x27,0x50,0x62,
+ 0xa5,0x00,0xe8,0xd5,0xdc,0xce,0xe6,0xf8,0xd1,0x9a,0xc2,0x31,0xf9,0x99,0x11,0xb5,
+ 0x5a,0xad,0x6f,0x68,0x03,0x2b,0x3d,0x95,0x67,0x9f,0xf2,0xca,0x9f,0x5b,0x4a,0x6f,
+ 0x6a,0xc3,0x56,0xb1,0x33,0x8e,0xc2,0x08,0x38,0x81,0xc0,0x12,0x87,0x55,0x42,0x62,
+ 0xc3,0x17,0xef,0x70,0xbc,0x47,0x5a,0x5e,0x81,0x63,0x3f,0x6e,0xdc,0x97,0xd9,0x21,
+ 0x1a,0xef,0xe4,0x75,0xac,0x11,0x19,0xc0,0x75,0x6d,0x23,0x18,0x05,0x72,0x73,
+};
+
+/**
+ * Implements credential_set_t.create_private_enumerator
+ */
+static enumerator_t* create_private_enumerator(private_load_tester_creds_t *this,
+ key_type_t type, identification_t *id)
+{
+ if (this->private == NULL)
+ {
+ return NULL;
+ }
+ if (type != KEY_ANY && type != KEY_RSA)
+ {
+ return NULL;
+ }
+ if (id)
+ {
+ identification_t *keyid;
+
+ keyid = this->private->get_id(this->private, id->get_type(id));
+ if (!keyid || !keyid->equals(keyid, id))
+ {
+ return NULL;
+ }
+ }
+ return enumerator_create_single(this->private, NULL);
+}
+
+/**
+ * Implements credential_set_t.create_cert_enumerator
+ */
+static enumerator_t* create_cert_enumerator(private_load_tester_creds_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ if (this->cert == NULL)
+ {
+ return NULL;
+ }
+ if (cert != CERT_ANY && cert != CERT_X509)
+ {
+ return NULL;
+ }
+ if (key != KEY_ANY && key != KEY_RSA)
+ {
+ return NULL;
+ }
+ if (id && !this->cert->has_subject(this->cert, id))
+ {
+ return NULL;
+ }
+ return enumerator_create_single(this->cert, NULL);
+}
+
+/**
+ * Implementation of load_tester_creds_t.destroy
+ */
+static void destroy(private_load_tester_creds_t *this)
+{
+ DESTROY_IF(this->private);
+ DESTROY_IF(this->cert);
+ free(this);
+}
+
+load_tester_creds_t *load_tester_creds_create()
+{
+ private_load_tester_creds_t *this = malloc_thing(private_load_tester_creds_t);
+
+ this->public.credential_set.create_shared_enumerator = (enumerator_t*(*)(credential_set_t*, shared_key_type_t, identification_t*, identification_t*))return_null;
+ this->public.credential_set.create_private_enumerator = (enumerator_t*(*) (credential_set_t*, key_type_t, identification_t*))create_private_enumerator;
+ this->public.credential_set.create_cert_enumerator = (enumerator_t*(*) (credential_set_t*, certificate_type_t, key_type_t,identification_t *, bool))create_cert_enumerator;
+ this->public.credential_set.create_cdp_enumerator = (enumerator_t*(*) (credential_set_t *,certificate_type_t, identification_t *))return_null;
+ this->public.credential_set.cache_cert = (void (*)(credential_set_t *, certificate_t *))nop;
+ this->public.destroy = (void(*) (load_tester_creds_t*))destroy;
+
+ this->private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_BLOB_ASN1_DER, chunk_create(private, sizeof(private)), BUILD_END);
+
+ this->cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, chunk_create(cert, sizeof(cert)), BUILD_END);
+
+ return &this->public;
+}
+
diff --git a/src/charon/plugins/load_tester/load_tester_creds.h b/src/charon/plugins/load_tester/load_tester_creds.h
new file mode 100644
index 000000000..bc092bd12
--- /dev/null
+++ b/src/charon/plugins/load_tester/load_tester_creds.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+/**
+ * @defgroup load_tester_creds_t load_tester_creds
+ * @{ @ingroup load_tester
+ */
+
+#ifndef LOAD_TESTER_CREDS_H_
+#define LOAD_TESTER_CREDS_H_
+
+#include <credentials/credential_set.h>
+
+typedef struct load_tester_creds_t load_tester_creds_t;
+
+/**
+ * Provide hard-coded credentials for load testing.
+ */
+struct load_tester_creds_t {
+
+ /**
+ * Implements credential set interface.
+ */
+ credential_set_t credential_set;
+
+ /**
+ * Destroy the backend.
+ */
+ void (*destroy)(load_tester_creds_t *this);
+};
+
+/**
+ * Create a credential set for load testing.
+ *
+ * @return credential set
+ */
+load_tester_creds_t *load_tester_creds_create();
+
+#endif /* LOAD_TESTER_CREDS_H_ @}*/
diff --git a/src/charon/plugins/load_tester/load_tester_ipsec.c b/src/charon/plugins/load_tester/load_tester_ipsec.c
new file mode 100644
index 000000000..9abd65195
--- /dev/null
+++ b/src/charon/plugins/load_tester/load_tester_ipsec.c
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#include "load_tester_ipsec.h"
+
+#include <time.h>
+
+typedef struct private_load_tester_ipsec_t private_load_tester_ipsec_t;
+
+/**
+ * Private variables and functions of kernel_pfkey class.
+ */
+struct private_load_tester_ipsec_t {
+ /**
+ * Public interface.
+ */
+ load_tester_ipsec_t public;
+
+ /**
+ * faked SPI counter
+ */
+ u_int32_t spi;
+};
+
+/**
+ * Implementation of kernel_interface_t.get_spi.
+ */
+static status_t get_spi(private_load_tester_ipsec_t *this,
+ host_t *src, host_t *dst,
+ protocol_id_t protocol, u_int32_t reqid,
+ u_int32_t *spi)
+{
+ *spi = ++this->spi;
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.get_cpi.
+ */
+static status_t get_cpi(private_load_tester_ipsec_t *this,
+ host_t *src, host_t *dst,
+ u_int32_t reqid, u_int16_t *cpi)
+{
+ return FAILED;
+}
+
+/**
+ * Implementation of kernel_interface_t.add_sa.
+ */
+static status_t add_sa(private_load_tester_ipsec_t *this,
+ host_t *src, host_t *dst, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid,
+ u_int64_t expire_soft, u_int64_t expire_hard,
+ u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key,
+ ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool encap, bool inbound)
+{
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.update_sa.
+ */
+static status_t update_sa(private_load_tester_ipsec_t *this,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
+ host_t *src, host_t *dst,
+ host_t *new_src, host_t *new_dst,
+ bool encap, bool new_encap)
+{
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.del_sa.
+ */
+static status_t del_sa(private_load_tester_ipsec_t *this, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi)
+{
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.add_policy.
+ */
+static status_t add_policy(private_load_tester_ipsec_t *this,
+ host_t *src, host_t *dst,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, u_int32_t spi,
+ protocol_id_t protocol, u_int32_t reqid,
+ ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
+ bool routed)
+{
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.query_policy.
+ */
+static status_t query_policy(private_load_tester_ipsec_t *this,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, u_int32_t *use_time)
+{
+ *use_time = time(NULL);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.del_policy.
+ */
+static status_t del_policy(private_load_tester_ipsec_t *this,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t direction, bool unrouted)
+{
+ return SUCCESS;
+}
+
+/**
+ * Implementation of kernel_interface_t.destroy.
+ */
+static void destroy(private_load_tester_ipsec_t *this)
+{
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+load_tester_ipsec_t *load_tester_ipsec_create()
+{
+ private_load_tester_ipsec_t *this = malloc_thing(private_load_tester_ipsec_t);
+
+ /* public functions */
+ this->public.interface.get_spi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
+ this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
+ this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool))add_sa;
+ this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,u_int16_t,host_t*,host_t*,host_t*,host_t*,bool,bool))update_sa;
+ this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,u_int32_t,protocol_id_t,u_int16_t))del_sa;
+ this->public.interface.add_policy = (status_t(*)(kernel_ipsec_t *this,host_t *, host_t *,traffic_selector_t *,traffic_selector_t *,policy_dir_t, u_int32_t,protocol_id_t, u_int32_t,ipsec_mode_t, u_int16_t, u_int16_t,bool))add_policy;
+ this->public.interface.query_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
+ this->public.interface.del_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,bool))del_policy;
+ this->public.interface.destroy = (void(*)(kernel_ipsec_t*)) destroy;
+
+ this->spi = 0;
+
+ return &this->public;
+}
+
diff --git a/src/charon/plugins/load_tester/load_tester_ipsec.h b/src/charon/plugins/load_tester/load_tester_ipsec.h
new file mode 100644
index 000000000..34a99dcbd
--- /dev/null
+++ b/src/charon/plugins/load_tester/load_tester_ipsec.h
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+/**
+ * @defgroup load_tester_ipsec_i load_tester_ipsec
+ * @{ @ingroup load_tester
+ */
+
+#ifndef LOAD_TESTER_IPSEC_H_
+#define LOAD_TESTER_IPSEC_H_
+
+#include <kernel/kernel_ipsec.h>
+
+typedef struct load_tester_ipsec_t load_tester_ipsec_t;
+
+/**
+ * Implementation of a fake kernel ipsec interface for load testing.
+ */
+struct load_tester_ipsec_t {
+
+ /**
+ * Implements kernel_ipsec_t interface
+ */
+ kernel_ipsec_t interface;
+};
+
+/**
+ * Create a faked kernel ipsec interface instance.
+ *
+ * @return kernel_load_tester_ipsec_t instance
+ */
+load_tester_ipsec_t *load_tester_ipsec_create();
+
+#endif /* LOAD_TESTER_IPSEC_H_ @} */
diff --git a/src/charon/plugins/load_tester/load_tester_listener.c b/src/charon/plugins/load_tester/load_tester_listener.c
new file mode 100644
index 000000000..991408a44
--- /dev/null
+++ b/src/charon/plugins/load_tester/load_tester_listener.c
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#include "load_tester_listener.h"
+
+#include <daemon.h>
+#include <processing/jobs/delete_ike_sa_job.h>
+
+typedef struct private_load_tester_listener_t private_load_tester_listener_t;
+
+/**
+ * Private data of an load_tester_listener_t object
+ */
+struct private_load_tester_listener_t {
+ /**
+ * Public part
+ */
+ load_tester_listener_t public;
+
+ /**
+ * Delete IKE_SA after it has been established
+ */
+ bool delete_after_established;
+};
+
+/**
+ * Implementation of listener_t.ike_state_change
+ */
+static bool ike_state_change(private_load_tester_listener_t *this,
+ ike_sa_t *ike_sa, ike_sa_state_t state)
+{
+ if (this->delete_after_established && state == IKE_ESTABLISHED)
+ {
+ charon->processor->queue_job(charon->processor,
+ (job_t*)delete_ike_sa_job_create(ike_sa->get_id(ike_sa), TRUE));
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of load_tester_listener_t.destroy
+ */
+static void destroy(private_load_tester_listener_t *this)
+{
+ free(this);
+}
+
+load_tester_listener_t *load_tester_listener_create()
+{
+ private_load_tester_listener_t *this = malloc_thing(private_load_tester_listener_t);
+
+ memset(&this->public.listener, 0, sizeof(listener_t));
+ this->public.listener.ike_state_change = (void*)ike_state_change;
+ this->public.destroy = (void(*) (load_tester_listener_t*))destroy;
+
+ this->delete_after_established = lib->settings->get_bool(lib->settings,
+ "charon.plugins.load_tester.delete_after_established", FALSE);
+
+ return &this->public;
+}
+
diff --git a/src/charon/plugins/load_tester/load_tester_listener.h b/src/charon/plugins/load_tester/load_tester_listener.h
new file mode 100644
index 000000000..28bb57d05
--- /dev/null
+++ b/src/charon/plugins/load_tester/load_tester_listener.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+/**
+ * @defgroup load_tester_listener_t load_tester_listener
+ * @{ @ingroup load_tester
+ */
+
+#ifndef LOAD_TESTER_LISTENER_H_
+#define LOAD_TESTER_LISTENER_H_
+
+#include <bus/bus.h>
+
+typedef struct load_tester_listener_t load_tester_listener_t;
+
+/**
+ * Provide hard-coded credentials for load testing.
+ */
+struct load_tester_listener_t {
+
+ /**
+ * Implements listener set interface.
+ */
+ listener_t listener;
+
+ /**
+ * Destroy the backend.
+ */
+ void (*destroy)(load_tester_listener_t *this);
+};
+
+/**
+ * Create a listener to handle special events during load test
+ *
+ * @return listener
+ */
+load_tester_listener_t *load_tester_listener_create();
+
+#endif /* LOAD_TESTER_LISTENER_H_ @}*/
diff --git a/src/charon/plugins/load_tester/load_tester_plugin.c b/src/charon/plugins/load_tester/load_tester_plugin.c
new file mode 100644
index 000000000..aff83a9a7
--- /dev/null
+++ b/src/charon/plugins/load_tester/load_tester_plugin.c
@@ -0,0 +1,175 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#include "load_tester_plugin.h"
+#include "load_tester_config.h"
+#include "load_tester_creds.h"
+#include "load_tester_ipsec.h"
+#include "load_tester_listener.h"
+
+#include <unistd.h>
+
+#include <daemon.h>
+#include <processing/jobs/callback_job.h>
+
+typedef struct private_load_tester_plugin_t private_load_tester_plugin_t;
+
+/**
+ * private data of load_tester plugin
+ */
+struct private_load_tester_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ load_tester_plugin_t public;
+
+ /**
+ * load_tester configuration backend
+ */
+ load_tester_config_t *config;
+
+ /**
+ * load_tester credential set implementation
+ */
+ load_tester_creds_t *creds;
+
+ /**
+ * event handler, listens on bus
+ */
+ load_tester_listener_t *listener;
+
+ /**
+ * number of iterations per thread
+ */
+ int iterations;
+
+ /**
+ * number of threads
+ */
+ int initiators;
+
+ /**
+ * delay between initiations, in ms
+ */
+ int delay;
+};
+
+/**
+ * Begin the load test
+ */
+static job_requeue_t do_load_test(private_load_tester_plugin_t *this)
+{
+ peer_cfg_t *peer_cfg;
+ child_cfg_t *child_cfg = NULL;;
+ enumerator_t *enumerator;
+ int i, s = 0, ms = 0;
+
+ if (this->delay)
+ {
+ s = this->delay / 1000;
+ ms = this->delay % 1000;
+ }
+ peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends,
+ "load-test");
+ if (peer_cfg)
+ {
+ enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+ if (enumerator->enumerate(enumerator, &child_cfg))
+ {
+ child_cfg->get_ref(child_cfg);
+ }
+ enumerator->destroy(enumerator);
+
+ if (child_cfg)
+ {
+ for (i = 0; this->iterations == 0 || i < this->iterations; i++)
+ {
+ charon->controller->initiate(charon->controller,
+ peer_cfg->get_ref(peer_cfg), child_cfg->get_ref(child_cfg),
+ NULL, NULL);
+
+ if (s)
+ {
+ sleep(s);
+ }
+ if (ms)
+ {
+ usleep(ms * 1000);
+ }
+ }
+ child_cfg->destroy(child_cfg);
+ }
+ peer_cfg->destroy(peer_cfg);
+ }
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_load_tester_plugin_t *this)
+{
+ charon->kernel_interface->remove_ipsec_interface(charon->kernel_interface,
+ (kernel_ipsec_constructor_t)load_tester_ipsec_create);
+ charon->backends->remove_backend(charon->backends, &this->config->backend);
+ charon->credentials->remove_set(charon->credentials, &this->creds->credential_set);
+ charon->bus->remove_listener(charon->bus, &this->listener->listener);
+ this->config->destroy(this->config);
+ this->creds->destroy(this->creds);
+ this->listener->destroy(this->listener);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *plugin_create()
+{
+ private_load_tester_plugin_t *this = malloc_thing(private_load_tester_plugin_t);
+ int i;
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ this->config = load_tester_config_create();
+ this->creds = load_tester_creds_create();
+ this->listener = load_tester_listener_create();
+ charon->backends->add_backend(charon->backends, &this->config->backend);
+ charon->credentials->add_set(charon->credentials, &this->creds->credential_set);
+ charon->bus->add_listener(charon->bus, &this->listener->listener);
+
+ if (lib->settings->get_bool(lib->settings,
+ "charon.plugins.load_tester.fake_kernel", FALSE))
+ {
+ charon->kernel_interface->add_ipsec_interface(charon->kernel_interface,
+ (kernel_ipsec_constructor_t)load_tester_ipsec_create);
+ }
+ this->delay = lib->settings->get_int(lib->settings,
+ "charon.plugins.load_tester.delay", 0);
+ this->iterations = lib->settings->get_int(lib->settings,
+ "charon.plugins.load_tester.iterations", 1);
+ this->initiators = lib->settings->get_int(lib->settings,
+ "charon.plugins.load_tester.initiators", 0);
+ for (i = 0; i < this->initiators; i++)
+ {
+ charon->processor->queue_job(charon->processor,
+ (job_t*)callback_job_create((callback_job_cb_t)do_load_test,
+ this, NULL, NULL));
+ }
+ return &this->public.plugin;
+}
+
diff --git a/src/charon/plugins/load_tester/load_tester_plugin.h b/src/charon/plugins/load_tester/load_tester_plugin.h
new file mode 100644
index 000000000..10088bfa2
--- /dev/null
+++ b/src/charon/plugins/load_tester/load_tester_plugin.h
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+/**
+ * @defgroup load_tester load_tester
+ * @ingroup cplugins
+ *
+ * @defgroup load_tester_plugin load_tester_plugin
+ * @{ @ingroup load_tester
+ */
+
+#ifndef LOAD_TESTER_PLUGIN_H_
+#define LOAD_TESTER_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct load_tester_plugin_t load_tester_plugin_t;
+
+/**
+ * Load tester plugin to inspect system core under high load.
+ *
+ * This plugin
+ */
+struct load_tester_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+/**
+ * Create a load_tester_plugin instance.
+ */
+plugin_t *plugin_create();
+
+#endif /* LOAD_TESTER_PLUGIN_H_ @}*/
diff --git a/src/charon/plugins/medcli/medcli_listener.c b/src/charon/plugins/medcli/medcli_listener.c
index 3b4156903..c057ea2b5 100644
--- a/src/charon/plugins/medcli/medcli_listener.c
+++ b/src/charon/plugins/medcli/medcli_listener.c
@@ -51,36 +51,55 @@ struct private_medcli_listener_t {
/**
* Implementation of bus_listener_t.signal.
*/
-static bool signal_(private_medcli_listener_t *this, signal_t signal,
- level_t level, int thread, ike_sa_t* ike_sa, void *data,
- char *format, va_list args)
+static void set_state(private_medcli_listener_t *this, char *alias,
+ mediated_state_t state)
{
- mediated_state_t state;
-
- if (!ike_sa)
+ this->db->execute(this->db, NULL,
+ "UPDATE Connection SET Status = ? WHERE Alias = ?",
+ DB_UINT, state, DB_TEXT, alias);
+}
+/**
+ * Implementation of listener_t.ike_state_change
+ */
+static bool ike_state_change(private_medcli_listener_t *this,
+ ike_sa_t *ike_sa, ike_sa_state_t state)
+{
+ if (ike_sa)
{
- return TRUE;
+ switch (state)
+ {
+ case IKE_CONNECTING:
+ set_state(this, ike_sa->get_name(ike_sa), STATE_CONNECTING);
+ break;
+ case IKE_DESTROYING:
+ set_state(this, ike_sa->get_name(ike_sa), STATE_DOWN);
+ default:
+ break;
+ }
}
+ return TRUE;
+}
- switch (signal)
+/**
+ * Implementation of listener_t.child_state_change
+ */
+static bool child_state_change(private_medcli_listener_t *this,
+ ike_sa_t *ike_sa, child_sa_t *child_sa, child_sa_state_t state)
+{
+ if (ike_sa && child_sa)
{
- case IKE_UP_START:
- state = STATE_CONNECTING;
- break;
- case IKE_UP_FAILED:
- case IKE_DOWN_SUCCESS:
- case IKE_DOWN_FAILED:
- state = STATE_DOWN;
- break;
- case IKE_UP_SUCCESS:
- state = STATE_UP;
- break;
- default:
- return TRUE;
+ switch (state)
+ {
+ case CHILD_INSTALLED:
+ set_state(this, child_sa->get_name(child_sa), STATE_UP);
+ break;
+ case CHILD_DESTROYING:
+ set_state(this, child_sa->get_name(child_sa), STATE_DOWN);
+ break;
+ default:
+ break;
+ }
}
- this->db->execute(this->db, NULL,
- "UPDATE Connection SET Status = ? WHERE Alias = ?",
- DB_UINT, state, DB_TEXT, ike_sa->get_name(ike_sa));
return TRUE;
}
@@ -91,7 +110,7 @@ static void destroy(private_medcli_listener_t *this)
{
this->db->execute(this->db, NULL, "UPDATE Connection SET Status = ?",
DB_UINT, STATE_DOWN);
- free(this);
+ free(this);
}
/**
@@ -100,8 +119,11 @@ static void destroy(private_medcli_listener_t *this)
medcli_listener_t *medcli_listener_create(database_t *db)
{
private_medcli_listener_t *this = malloc_thing(private_medcli_listener_t);
-
- this->public.listener.signal = (bool(*)(bus_listener_t*,signal_t,level_t,int,ike_sa_t*,void*,char*,va_list))signal_;
+
+ memset(&this->public.listener, 0, sizeof(listener_t));
+
+ this->public.listener.ike_state_change = (void*)ike_state_change;
+ this->public.listener.child_state_change = (void*)child_state_change;
this->public.destroy = (void (*)(medcli_listener_t*))destroy;
this->db = db;
diff --git a/src/charon/plugins/medcli/medcli_listener.h b/src/charon/plugins/medcli/medcli_listener.h
index f07218d78..4cec3caad 100644
--- a/src/charon/plugins/medcli/medcli_listener.h
+++ b/src/charon/plugins/medcli/medcli_listener.h
@@ -36,7 +36,7 @@ struct medcli_listener_t {
/**
* Implements bus_listener_t interface
*/
- bus_listener_t listener;
+ listener_t listener;
/**
* Destroy the credentials databse.
diff --git a/src/charon/plugins/nm/Makefile.am b/src/charon/plugins/nm/Makefile.am
index 107ca1a31..bb5436443 100644
--- a/src/charon/plugins/nm/Makefile.am
+++ b/src/charon/plugins/nm/Makefile.am
@@ -25,4 +25,4 @@ EXTRA_DIST = gnome/configure gnome/po/LINGUAS gnome/po/POTFILES.in gnome/po/Make
gnome/config.sub gnome/missing
gnome/configure : gnome/configure.in
- cd gnome && ./autogen.sh; cd ..
+ (cd `dirname $<` && ./autogen.sh)
diff --git a/src/charon/plugins/nm/Makefile.in b/src/charon/plugins/nm/Makefile.in
index 46e4ab851..4f75da14f 100644
--- a/src/charon/plugins/nm/Makefile.in
+++ b/src/charon/plugins/nm/Makefile.in
@@ -513,7 +513,7 @@ uninstall-am: uninstall-pluginLTLIBRARIES
gnome/configure : gnome/configure.in
- cd gnome && ./autogen.sh; cd ..
+ (cd `dirname $<` && ./autogen.sh)
# 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/charon/plugins/nm/nm_creds.c b/src/charon/plugins/nm/nm_creds.c
index f165653ae..e7cd640a7 100644
--- a/src/charon/plugins/nm/nm_creds.c
+++ b/src/charon/plugins/nm/nm_creds.c
@@ -15,12 +15,10 @@
* $Id$
*/
-#define _GNU_SOURCE
-#include <pthread.h>
-
#include "nm_creds.h"
#include <daemon.h>
+#include <utils/mutex.h>
typedef struct private_nm_creds_t private_nm_creds_t;
@@ -62,7 +60,7 @@ struct private_nm_creds_t {
/**
* read/write lock
*/
- pthread_rwlock_t lock;
+ rwlock_t *lock;
};
/**
@@ -91,10 +89,10 @@ static enumerator_t *create_usercert_enumerator(private_nm_creds_t *this,
}
public->destroy(public);
}
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
return enumerator_create_cleaner(
enumerator_create_single(this->usercert, NULL),
- (void*)pthread_rwlock_unlock, &this->lock);
+ (void*)this->lock->unlock, this->lock);
}
/**
@@ -138,9 +136,9 @@ static enumerator_t* create_cert_enumerator(private_nm_creds_t *this,
}
public->destroy(public);
}
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
return enumerator_create_cleaner(enumerator_create_single(this->cert, NULL),
- (void*)pthread_rwlock_unlock, &this->lock);
+ (void*)this->lock->unlock, this->lock);
}
/**
@@ -167,9 +165,9 @@ static enumerator_t* create_private_enumerator(private_nm_creds_t *this,
return NULL;
}
}
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
return enumerator_create_cleaner(enumerator_create_single(this->key, NULL),
- (void*)pthread_rwlock_unlock, &this->lock);
+ (void*)this->lock->unlock, this->lock);
}
/**
@@ -205,7 +203,7 @@ static bool shared_enumerate(shared_enumerator_t *this, shared_key_t **key,
static void shared_destroy(shared_enumerator_t *this)
{
this->key->destroy(this->key);
- pthread_rwlock_unlock(&this->this->lock);
+ this->this->lock->unlock(this->this->lock);
free(this);
}
/**
@@ -235,7 +233,7 @@ static enumerator_t* create_shared_enumerator(private_nm_creds_t *this,
enumerator->public.destroy = (void*)shared_destroy;
enumerator->this = this;
enumerator->done = FALSE;
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
enumerator->key = shared_key_create(type,
chunk_clone(chunk_create(this->pass,
strlen(this->pass))));
@@ -247,10 +245,10 @@ static enumerator_t* create_shared_enumerator(private_nm_creds_t *this,
*/
static void set_certificate(private_nm_creds_t *this, certificate_t *cert)
{
- pthread_rwlock_wrlock(&this->lock);
+ this->lock->write_lock(this->lock);
DESTROY_IF(this->cert);
this->cert = cert;
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
}
/**
@@ -259,14 +257,14 @@ static void set_certificate(private_nm_creds_t *this, certificate_t *cert)
static void set_username_password(private_nm_creds_t *this, identification_t *id,
char *password)
{
- pthread_rwlock_wrlock(&this->lock);
+ this->lock->write_lock(this->lock);
DESTROY_IF(this->user);
/* for EAP authentication, we use always use ID_EAP type */
this->user = identification_create_from_encoding(ID_EAP,
id->get_encoding(id));
free(this->pass);
this->pass = password ? strdup(password) : NULL;
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
}
/**
@@ -275,12 +273,12 @@ static void set_username_password(private_nm_creds_t *this, identification_t *id
static void set_cert_and_key(private_nm_creds_t *this, certificate_t *cert,
private_key_t *key)
{
- pthread_rwlock_wrlock(&this->lock);
+ this->lock->write_lock(this->lock);
DESTROY_IF(this->key);
DESTROY_IF(this->usercert);
this->key = key;
this->usercert = cert;
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
}
/**
@@ -306,7 +304,7 @@ static void clear(private_nm_creds_t *this)
static void destroy(private_nm_creds_t *this)
{
clear(this);
- pthread_rwlock_destroy(&this->lock);
+ this->lock->destroy(this->lock);
free(this);
}
@@ -328,7 +326,7 @@ nm_creds_t *nm_creds_create()
this->public.clear = (void(*)(nm_creds_t*))clear;
this->public.destroy = (void(*)(nm_creds_t*))destroy;
- pthread_rwlock_init(&this->lock, NULL);
+ this->lock = rwlock_create(RWLOCK_DEFAULT);
this->cert = NULL;
this->user = NULL;
diff --git a/src/charon/plugins/nm/nm_service.c b/src/charon/plugins/nm/nm_service.c
index fbc094a3b..f90bfa448 100644
--- a/src/charon/plugins/nm/nm_service.c
+++ b/src/charon/plugins/nm/nm_service.c
@@ -34,7 +34,7 @@ G_DEFINE_TYPE(NMStrongswanPlugin, nm_strongswan_plugin, NM_TYPE_VPN_PLUGIN)
* Private data of NMStrongswanPlugin
*/
typedef struct {
- bus_listener_t listener;
+ listener_t listener;
ike_sa_t *ike_sa;
NMVPNPlugin *plugin;
nm_creds_t *creds;
@@ -45,109 +45,88 @@ typedef struct {
NM_TYPE_STRONGSWAN_PLUGIN, NMStrongswanPluginPrivate))
/**
- * convert a traffic selector address range to subnet and its mask.
+ * signal IPv4 config to NM, set connection as established
*/
-static u_int ts2subnet(traffic_selector_t* ts, u_int8_t *mask)
+static void signal_ipv4_config(NMVPNPlugin *plugin,
+ ike_sa_t *ike_sa, child_sa_t *child_sa)
{
- /* there is no way to do this cleanly, as the address range may
- * be anything else but a subnet. We use from_addr as subnet
- * and try to calculate a usable subnet mask.
- */
- int byte, bit, net;
- bool found = FALSE;
- chunk_t from, to;
- size_t size = (ts->get_type(ts) == TS_IPV4_ADDR_RANGE) ? 4 : 16;
+ GValue *val;
+ GHashTable *config;
+ host_t *me, *other;
- from = ts->get_from_address(ts);
- to = ts->get_to_address(ts);
+ config = g_hash_table_new(g_str_hash, g_str_equal);
+ me = ike_sa->get_my_host(ike_sa);
+ other = ike_sa->get_other_host(ike_sa);
- *mask = (size * 8);
- /* go trough all bits of the addresses, beginning in the front.
- * as long as they are equal, the subnet gets larger
- */
- for (byte = 0; byte < size; byte++)
- {
- for (bit = 7; bit >= 0; bit--)
- {
- if ((1<<bit & from.ptr[byte]) != (1<<bit & to.ptr[byte]))
- {
- *mask = ((7 - bit) + (byte * 8));
- found = TRUE;
- break;
- }
- }
- if (found)
- {
- break;
- }
- }
- net = *(u_int32_t*)from.ptr;
- chunk_free(&from);
- chunk_free(&to);
- return net;
+ /* NM requires a tundev, but netkey does not use one. Passing an invalid
+ * iface makes NM complain, but it accepts it without fiddling on eth0. */
+ val = g_slice_new0 (GValue);
+ g_value_init (val, G_TYPE_STRING);
+ g_value_set_string (val, "none");
+ g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, val);
+
+ val = g_slice_new0(GValue);
+ g_value_init(val, G_TYPE_UINT);
+ g_value_set_uint(val, *(u_int32_t*)me->get_address(me).ptr);
+ g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, val);
+
+ val = g_slice_new0(GValue);
+ g_value_init(val, G_TYPE_UINT);
+ g_value_set_uint(val, me->get_address(me).len * 8);
+ g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val);
+
+ nm_vpn_plugin_set_ip4_config(plugin, config);
}
/**
- * signal IPv4 config to NM, set connection as established
+ * signal failure to NM, connecting failed
*/
-static void signal_ipv4_config(NMVPNPlugin *plugin, child_sa_t *child_sa)
+static void signal_failure(NMVPNPlugin *plugin)
{
- linked_list_t *list;
- traffic_selector_t *ts = NULL;
- enumerator_t *enumerator;
+ /* TODO: NM does not handle this failure!?
+ nm_vpn_plugin_failure(plugin, NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED); */
+ nm_vpn_plugin_set_state(plugin, NM_VPN_SERVICE_STATE_STOPPED);
+}
+
+/**
+ * Implementation of listener_t.ike_state_change
+ */
+static bool ike_state_change(listener_t *listener, ike_sa_t *ike_sa,
+ ike_sa_state_t state)
+{
+ NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
- list = child_sa->get_traffic_selectors(child_sa, FALSE);
- enumerator = list->create_enumerator(list);
- while (enumerator->enumerate(enumerator, &ts))
+ if (private->ike_sa == ike_sa)
{
- GValue *val;
- GHashTable *config;
- u_int8_t mask;
-
- config = g_hash_table_new(g_str_hash, g_str_equal);
-
- val = g_slice_new0(GValue);
- g_value_init(val, G_TYPE_UINT);
- g_value_set_uint(val, ts2subnet(ts, &mask));
- g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, val);
-
- val = g_slice_new0(GValue);
- g_value_init(val, G_TYPE_UINT);
- g_value_set_uint(val, mask);
- g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val);
-
- nm_vpn_plugin_set_ip4_config(plugin, config);
+ switch (state)
+ {
+ case IKE_DESTROYING:
+ signal_failure(private->plugin);
+ return FALSE;
+ default:
+ break;
+ }
}
- enumerator->destroy(enumerator);
+ return TRUE;
}
/**
- * Bus listen function to wait for SA establishing
+ * Implementation of listener_t.child_state_change
*/
-bool listen_bus(bus_listener_t *listener, signal_t signal, level_t level,
- int thread, ike_sa_t *ike_sa, void *data,
- char* format, va_list args)
+static bool child_state_change(listener_t *listener, ike_sa_t *ike_sa,
+ child_sa_t *child_sa, child_sa_state_t state)
{
NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
-
+
if (private->ike_sa == ike_sa)
{
- switch (signal)
+ switch (state)
{
- case CHD_UP_SUCCESS:
- if (data)
- {
- signal_ipv4_config(private->plugin, (child_sa_t*)data);
- return FALSE;
- }
- /* FALL */
- case IKE_UP_FAILED:
- case CHD_UP_FAILED:
- /* TODO: NM does not handle this failure!?
- nm_vpn_plugin_failure(private->plugin,
- NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED); */
- nm_vpn_plugin_set_state(private->plugin,
- NM_VPN_SERVICE_STATE_STOPPED);
+ case CHILD_INSTALLED:
+ signal_ipv4_config(private->plugin, ike_sa, child_sa);
+ return FALSE;
+ case CHILD_DESTROYING:
+ signal_failure(private->plugin);
return FALSE;
default:
break;
@@ -462,8 +441,13 @@ static gboolean disconnect(NMVPNPlugin *plugin, GError **err)
*/
static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin)
{
- NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->plugin = NM_VPN_PLUGIN(plugin);
- NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->listener.signal = listen_bus;
+ NMStrongswanPluginPrivate *private;
+
+ private = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
+ private->plugin = NM_VPN_PLUGIN(plugin);
+ memset(&private->listener.log, 0, sizeof(listener_t));
+ private->listener.ike_state_change = ike_state_change;
+ private->listener.child_state_change = child_state_change;
}
/**
diff --git a/src/charon/plugins/smp/smp.c b/src/charon/plugins/smp/smp.c
index 0870cad4c..237e9d86a 100644
--- a/src/charon/plugins/smp/smp.c
+++ b/src/charon/plugins/smp/smp.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: smp.c 4358 2008-09-25 13:56:23Z tobias $
+ * $Id: smp.c 4446 2008-10-15 12:24:44Z martin $
*/
#include <stdlib.h>
@@ -181,19 +181,13 @@ static void write_childend(xmlTextWriterPtr writer, child_sa_t *child, bool loca
*/
static void write_child(xmlTextWriterPtr writer, child_sa_t *child)
{
- ipsec_mode_t mode;
- encryption_algorithm_t encr;
- integrity_algorithm_t int_algo;
- size_t encr_len, int_len;
- u_int32_t rekey, use_in, use_out, use_fwd;
child_cfg_t *config;
config = child->get_config(child);
- child->get_stats(child, &mode, &encr, &encr_len, &int_algo, &int_len,
- &rekey, &use_in, &use_out, &use_fwd);
xmlTextWriterStartElement(writer, "childsa");
- xmlTextWriterWriteFormatElement(writer, "reqid", "%d", child->get_reqid(child));
+ xmlTextWriterWriteFormatElement(writer, "reqid", "%d",
+ child->get_reqid(child));
xmlTextWriterWriteFormatElement(writer, "childconfig", "%s",
config->get_name(config));
xmlTextWriterStartElement(writer, "local");
@@ -359,15 +353,15 @@ static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr write
/**
* callback which logs to a XML writer
*/
-static bool xml_callback(xmlTextWriterPtr writer, signal_t signal, level_t level,
- ike_sa_t* ike_sa, void *data, char* format, va_list args)
+static bool xml_callback(xmlTextWriterPtr writer, debug_t group, level_t level,
+ ike_sa_t* ike_sa, char* format, va_list args)
{
if (level <= 1)
{
/* <item> */
xmlTextWriterStartElement(writer, "item");
xmlTextWriterWriteFormatAttribute(writer, "level", "%d", level);
- xmlTextWriterWriteFormatAttribute(writer, "source", "%N", signal_names, signal);
+ xmlTextWriterWriteFormatAttribute(writer, "source", "%N", debug_names, group);
xmlTextWriterWriteFormatAttribute(writer, "thread", "%u", pthread_self());
xmlTextWriterWriteVFormatString(writer, format, args);
xmlTextWriterEndElement(writer);
diff --git a/src/charon/plugins/sql/pool.c b/src/charon/plugins/sql/pool.c
index b3ad72ab2..8f5dc54dd 100644
--- a/src/charon/plugins/sql/pool.c
+++ b/src/charon/plugins/sql/pool.c
@@ -36,14 +36,6 @@ database_t *db;
host_t *start = NULL, *end = NULL;
/**
- * create a host from a blob
- */
-static host_t *host_create_from_blob(chunk_t blob)
-{
- return host_create_from_chunk(blob.len == 4 ? AF_INET : AF_INET6, blob, 0);
-}
-
-/**
* calculate the size of a pool using start and end address chunk
*/
static u_int get_pool_size(chunk_t start, chunk_t end)
@@ -132,8 +124,8 @@ static void status(void)
found = TRUE;
}
- start = host_create_from_blob(start_chunk);
- end = host_create_from_blob(end_chunk);
+ start = host_create_from_chunk(AF_UNSPEC, start_chunk, 0);
+ end = host_create_from_chunk(AF_UNSPEC, end_chunk, 0);
size = get_pool_size(start_chunk, end_chunk);
printf("%8s %15H %15H ", name, start, end);
if (timeout)
@@ -541,7 +533,7 @@ static void leases(char *filter, bool utc)
printf("%-8s %-15s %-7s %-*s %-*s %s\n",
"name", "address", "status", len, "start", len, "end", "identity");
}
- address = host_create_from_blob(address_chunk);
+ address = host_create_from_chunk(AF_UNSPEC, address_chunk, 0);
identity = identification_create_from_encoding(identity_type, identity_chunk);
printf("%-8s %-15H ", name, address);
diff --git a/src/charon/plugins/sql/sql_attribute.c b/src/charon/plugins/sql/sql_attribute.c
index 1e5c28966..486a432ca 100644
--- a/src/charon/plugins/sql/sql_attribute.c
+++ b/src/charon/plugins/sql/sql_attribute.c
@@ -17,6 +17,8 @@
#include "sql_attribute.h"
+#include <time.h>
+
#include <daemon.h>
typedef struct private_sql_attribute_t private_sql_attribute_t;
@@ -43,22 +45,6 @@ struct private_sql_attribute_t {
};
/**
- * read a host_t address from the addresses table
- */
-static host_t *host_from_chunk(chunk_t chunk)
-{
- switch (chunk.len)
- {
- case 4:
- return host_create_from_chunk(AF_INET, chunk, 0);
- case 16:
- return host_create_from_chunk(AF_INET6, chunk, 0);
- default:
- return NULL;
- }
-}
-
-/**
* lookup/insert an identity
*/
static u_int get_identity(private_sql_attribute_t *this, identification_t *id)
@@ -143,7 +129,7 @@ static host_t *get_address(private_sql_attribute_t *this, char *name,
"WHERE id = ? AND identity = ? AND released != 0",
DB_UINT, now, DB_UINT, id, DB_UINT, identity) > 0)
{
- host = host_from_chunk(address);
+ host = host_create_from_chunk(AF_UNSPEC, address, 0);
if (host)
{
DBG1(DBG_CFG, "acquired existing lease "
@@ -175,7 +161,7 @@ static host_t *get_address(private_sql_attribute_t *this, char *name,
DB_UINT, now, DB_UINT, identity,
DB_UINT, id, DB_UINT, now - timeout) > 0)
{
- host = host_from_chunk(address);
+ host = host_create_from_chunk(AF_UNSPEC, address, 0);
if (host)
{
DBG1(DBG_CFG, "acquired new lease "
diff --git a/src/charon/plugins/sql/sql_logger.c b/src/charon/plugins/sql/sql_logger.c
index 6a87f9f1d..4cbaaa3e6 100644
--- a/src/charon/plugins/sql/sql_logger.c
+++ b/src/charon/plugins/sql/sql_logger.c
@@ -49,13 +49,11 @@ struct private_sql_logger_t {
bool recursive;
};
-
/**
- * Implementation of bus_listener_t.signal.
+ * Implementation of bus_listener_t.log.
*/
-static bool signal_(private_sql_logger_t *this, signal_t signal, level_t level,
- int thread, ike_sa_t* ike_sa, void *data,
- char *format, va_list args)
+static bool log_(private_sql_logger_t *this, debug_t group, level_t level,
+ int thread, ike_sa_t* ike_sa, char *format, va_list args)
{
if (this->recursive)
{
@@ -111,7 +109,7 @@ static bool signal_(private_sql_logger_t *this, signal_t signal, level_t level,
DB_BLOB, remote_host->get_address(remote_host));
this->db->execute(this->db, NULL, "INSERT INTO logs ("
"local_spi, signal, level, msg) VALUES (?, ?, ?, ?)",
- DB_BLOB, local_spi, DB_INT, signal, DB_INT, level,
+ DB_BLOB, local_spi, DB_INT, group, DB_INT, level,
DB_TEXT, buffer);
}
this->recursive = FALSE;
@@ -134,7 +132,8 @@ sql_logger_t *sql_logger_create(database_t *db)
{
private_sql_logger_t *this = malloc_thing(private_sql_logger_t);
- this->public.listener.signal = (bool(*)(bus_listener_t*,signal_t,level_t,int,ike_sa_t*,void*,char*,va_list))signal_;
+ memset(&this->public.listener, 0, sizeof(listener_t));
+ this->public.listener.log = (bool(*)(listener_t*,debug_t,level_t,int,ike_sa_t*,char*,va_list))log_;
this->public.destroy = (void(*)(sql_logger_t*))destroy;
this->db = db;
diff --git a/src/charon/plugins/sql/sql_logger.h b/src/charon/plugins/sql/sql_logger.h
index 30507bcaf..a2c6fb5e9 100644
--- a/src/charon/plugins/sql/sql_logger.h
+++ b/src/charon/plugins/sql/sql_logger.h
@@ -36,7 +36,7 @@ struct sql_logger_t {
/**
* Implements bus_listener_t interface
*/
- bus_listener_t listener;
+ listener_t listener;
/**
* Destry the backend.
diff --git a/src/charon/plugins/stroke/stroke_ca.c b/src/charon/plugins/stroke/stroke_ca.c
index 8569f49c3..54356436f 100644
--- a/src/charon/plugins/stroke/stroke_ca.c
+++ b/src/charon/plugins/stroke/stroke_ca.c
@@ -16,12 +16,10 @@
* $Id$
*/
-#define _GNU_SOURCE
-#include <pthread.h>
-
#include "stroke_ca.h"
#include "stroke_cred.h"
+#include <utils/mutex.h>
#include <utils/linked_list.h>
#include <crypto/hashers/hasher.h>
@@ -42,7 +40,7 @@ struct private_stroke_ca_t {
/**
* read-write lock to lists
*/
- pthread_rwlock_t lock;
+ rwlock_t *lock;
/**
* list of starters CA sections and its certificates (ca_section_t)
@@ -136,7 +134,7 @@ typedef struct {
*/
static void cdp_data_destroy(cdp_data_t *data)
{
- pthread_rwlock_unlock(&data->this->lock);
+ data->this->lock->unlock(data->this->lock);
free(data);
}
@@ -236,7 +234,7 @@ static enumerator_t *create_cdp_enumerator(private_stroke_ca_t *this,
data->type = type;
data->id = id;
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
return enumerator_create_nested(this->sections->create_enumerator(this->sections),
(type == CERT_X509) ? (void*)create_inner_cdp_hashandurl : (void*)create_inner_cdp,
data, (void*)cdp_data_destroy);
@@ -278,9 +276,9 @@ static void add(private_stroke_ca_t *this, stroke_msg_t *msg)
{
ca->certuribase = strdup(msg->add_ca.certuribase);
}
- pthread_rwlock_wrlock(&this->lock);
+ this->lock->write_lock(this->lock);
this->sections->insert_last(this->sections, ca);
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
DBG1(DBG_CFG, "added ca '%s'", msg->add_ca.name);
}
}
@@ -293,7 +291,7 @@ static void del(private_stroke_ca_t *this, stroke_msg_t *msg)
enumerator_t *enumerator;
ca_section_t *ca = NULL;
- pthread_rwlock_wrlock(&this->lock);
+ this->lock->write_lock(this->lock);
enumerator = this->sections->create_enumerator(this->sections);
while (enumerator->enumerate(enumerator, &ca))
{
@@ -305,7 +303,7 @@ static void del(private_stroke_ca_t *this, stroke_msg_t *msg)
ca = NULL;
}
enumerator->destroy(enumerator);
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
if (ca == NULL)
{
DBG1(DBG_CFG, "no ca named '%s' found\n", msg->del_ca.name);
@@ -356,7 +354,7 @@ static void check_for_hash_and_url(private_stroke_ca_t *this, certificate_t* cer
return;
}
- pthread_rwlock_wrlock(&this->lock);
+ this->lock->write_lock(this->lock);
enumerator = this->sections->create_enumerator(this->sections);
while (enumerator->enumerate(enumerator, (void**)&section))
{
@@ -372,7 +370,7 @@ static void check_for_hash_and_url(private_stroke_ca_t *this, certificate_t* cer
}
}
enumerator->destroy(enumerator);
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
hasher->destroy(hasher);
}
@@ -386,7 +384,7 @@ static void list(private_stroke_ca_t *this, stroke_msg_t *msg, FILE *out)
ca_section_t *section;
enumerator_t *enumerator;
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
enumerator = this->sections->create_enumerator(this->sections);
while (enumerator->enumerate(enumerator, (void**)&section))
{
@@ -419,7 +417,7 @@ static void list(private_stroke_ca_t *this, stroke_msg_t *msg, FILE *out)
}
}
enumerator->destroy(enumerator);
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
}
/**
@@ -428,7 +426,7 @@ static void list(private_stroke_ca_t *this, stroke_msg_t *msg, FILE *out)
static void destroy(private_stroke_ca_t *this)
{
this->sections->destroy_function(this->sections, (void*)ca_section_destroy);
- pthread_rwlock_destroy(&this->lock);
+ this->lock->destroy(this->lock);
free(this);
}
@@ -451,7 +449,7 @@ stroke_ca_t *stroke_ca_create(stroke_cred_t *cred)
this->public.destroy = (void(*)(stroke_ca_t*))destroy;
this->sections = linked_list_create();
- pthread_rwlock_init(&this->lock, NULL);
+ this->lock = rwlock_create(RWLOCK_DEFAULT);
this->cred = cred;
return &this->public;
diff --git a/src/charon/plugins/stroke/stroke_config.c b/src/charon/plugins/stroke/stroke_config.c
index f10fe2051..cb91ecb72 100644
--- a/src/charon/plugins/stroke/stroke_config.c
+++ b/src/charon/plugins/stroke/stroke_config.c
@@ -19,6 +19,7 @@
#include <daemon.h>
#include <utils/mutex.h>
+#include <utils/lexparser.h>
typedef struct private_stroke_config_t private_stroke_config_t;
@@ -774,7 +775,8 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
msg->add_conn.mode, dpd, dpd, msg->add_conn.ipcomp);
-
+ child_cfg->set_mipv6_options(child_cfg, msg->add_conn.proxy_mode,
+ msg->add_conn.install_policy);
add_ts(this, &msg->add_conn.me, child_cfg, TRUE);
add_ts(this, &msg->add_conn.other, child_cfg, FALSE);
diff --git a/src/charon/plugins/stroke/stroke_control.c b/src/charon/plugins/stroke/stroke_control.c
index ed9dd7b16..08d50519c 100644
--- a/src/charon/plugins/stroke/stroke_control.c
+++ b/src/charon/plugins/stroke/stroke_control.c
@@ -55,8 +55,8 @@ struct stroke_log_info_t {
/**
* logging to the stroke interface
*/
-static bool stroke_log(stroke_log_info_t *info, signal_t signal, level_t level,
- ike_sa_t *ike_sa, void *data, char *format, va_list args)
+static bool stroke_log(stroke_log_info_t *info, debug_t group, level_t level,
+ ike_sa_t *ike_sa, char *format, va_list args)
{
if (level <= info->level)
{
diff --git a/src/charon/plugins/stroke/stroke_cred.c b/src/charon/plugins/stroke/stroke_cred.c
index c699a083e..23a6f99b0 100644
--- a/src/charon/plugins/stroke/stroke_cred.c
+++ b/src/charon/plugins/stroke/stroke_cred.c
@@ -15,8 +15,6 @@
* $Id$
*/
-#define _GNU_SOURCE
-#include <pthread.h>
#include <sys/stat.h>
#include <limits.h>
@@ -28,6 +26,7 @@
#include <credentials/certificates/ac.h>
#include <utils/linked_list.h>
#include <utils/lexparser.h>
+#include <utils/mutex.h>
#include <asn1/pem.h>
#include <daemon.h>
@@ -73,7 +72,7 @@ struct private_stroke_cred_t {
/**
* read-write lock to lists
*/
- pthread_rwlock_t lock;
+ rwlock_t *lock;
/**
* cache CRLs to disk?
@@ -94,7 +93,7 @@ typedef struct {
*/
static void id_data_destroy(id_data_t *data)
{
- pthread_rwlock_unlock(&data->this->lock);
+ data->this->lock->unlock(data->this->lock);
free(data);
}
@@ -140,7 +139,7 @@ static enumerator_t* create_private_enumerator(private_stroke_cred_t *this,
data->this = this;
data->id = id;
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
return enumerator_create_filter(this->private->create_enumerator(this->private),
(void*)private_filter, data,
(void*)id_data_destroy);
@@ -241,7 +240,7 @@ static enumerator_t* create_cert_enumerator(private_stroke_cred_t *this,
data->this = this;
data->id = id;
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
return enumerator_create_filter(this->certs->create_enumerator(this->certs),
(cert == CERT_X509_CRL)? (void*)crl_filter : (void*)ac_filter,
data, (void*)id_data_destroy);
@@ -254,7 +253,7 @@ static enumerator_t* create_cert_enumerator(private_stroke_cred_t *this,
data->this = this;
data->id = id;
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
return enumerator_create_filter(this->certs->create_enumerator(this->certs),
(void*)certs_filter, data,
(void*)id_data_destroy);
@@ -272,7 +271,7 @@ typedef struct {
*/
static void shared_data_destroy(shared_data_t *data)
{
- pthread_rwlock_unlock(&data->this->lock);
+ data->this->lock->unlock(data->this->lock);
free(data);
}
@@ -324,7 +323,7 @@ static enumerator_t* create_shared_enumerator(private_stroke_cred_t *this,
data->me = me;
data->other = other;
data->type = type;
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
return enumerator_create_filter(this->shared->create_enumerator(this->shared),
(void*)shared_filter, data,
(void*)shared_data_destroy);
@@ -339,7 +338,7 @@ static certificate_t* add_cert(private_stroke_cred_t *this, certificate_t *cert)
enumerator_t *enumerator;
bool new = TRUE;
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
enumerator = this->certs->create_enumerator(this->certs);
while (enumerator->enumerate(enumerator, (void**)&current))
{
@@ -358,7 +357,7 @@ static certificate_t* add_cert(private_stroke_cred_t *this, certificate_t *cert)
{
this->certs->insert_last(this->certs, cert);
}
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
return cert;
}
@@ -400,7 +399,7 @@ static bool add_crl(private_stroke_cred_t *this, crl_t* crl)
enumerator_t *enumerator;
bool new = TRUE, found = FALSE;
- pthread_rwlock_wrlock(&this->lock);
+ this->lock->write_lock(this->lock);
enumerator = this->certs->create_enumerator(this->certs);
while (enumerator->enumerate(enumerator, (void**)&current))
{
@@ -448,7 +447,7 @@ static bool add_crl(private_stroke_cred_t *this, crl_t* crl)
{
this->certs->insert_last(this->certs, cert);
}
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
return new;
}
@@ -459,9 +458,9 @@ static bool add_ac(private_stroke_cred_t *this, ac_t* ac)
{
certificate_t *cert = &ac->certificate;
- pthread_rwlock_wrlock(&this->lock);
+ this->lock->write_lock(this->lock);
this->certs->insert_last(this->certs, cert);
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
return TRUE;
}
@@ -698,7 +697,7 @@ static void load_secrets(private_stroke_cred_t *this)
fclose(fd);
src = chunk;
- pthread_rwlock_wrlock(&this->lock);
+ this->lock->write_lock(this->lock);
while (this->shared->remove_last(this->shared,
(void**)&shared) == SUCCESS)
{
@@ -868,7 +867,7 @@ static void load_secrets(private_stroke_cred_t *this)
}
}
error:
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
chunk_clear(&chunk);
}
@@ -949,7 +948,7 @@ static void destroy(private_stroke_cred_t *this)
this->certs->destroy_offset(this->certs, offsetof(certificate_t, destroy));
this->shared->destroy_offset(this->shared, offsetof(shared_key_t, destroy));
this->private->destroy_offset(this->private, offsetof(private_key_t, destroy));
- pthread_rwlock_destroy(&this->lock);
+ this->lock->destroy(this->lock);
free(this);
}
@@ -974,7 +973,7 @@ stroke_cred_t *stroke_cred_create()
this->certs = linked_list_create();
this->shared = linked_list_create();
this->private = linked_list_create();
- pthread_rwlock_init(&this->lock, NULL);
+ this->lock = rwlock_create(RWLOCK_DEFAULT);
load_certs(this);
load_secrets(this);
diff --git a/src/charon/plugins/stroke/stroke_list.c b/src/charon/plugins/stroke/stroke_list.c
index d531dca47..7d0ad4557 100644
--- a/src/charon/plugins/stroke/stroke_list.c
+++ b/src/charon/plugins/stroke/stroke_list.c
@@ -17,6 +17,8 @@
#include "stroke_list.h"
+#include <time.h>
+
#include <daemon.h>
#include <utils/linked_list.h>
#include <credentials/certificates/x509.h>
@@ -79,25 +81,32 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
if (all)
{
- char *ike_proposal = ike_sa->get_proposal(ike_sa);
-
+ proposal_t *ike_proposal;
+
+ ike_proposal = ike_sa->get_proposal(ike_sa);
+
fprintf(out, "%12s[%d]: IKE SPIs: %.16llx_i%s %.16llx_r%s",
ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
id->get_initiator_spi(id), id->is_initiator(id) ? "*" : "",
id->get_responder_spi(id), id->is_initiator(id) ? "" : "*");
-
-
+
+
if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
{
- u_int32_t rekey = ike_sa->get_statistic(ike_sa, STAT_REKEY_TIME);
- u_int32_t reauth = ike_sa->get_statistic(ike_sa, STAT_REAUTH_TIME);
-
+ u_int32_t rekey, reauth, now;
+
+ now = time(NULL);
+ rekey = ike_sa->get_statistic(ike_sa, STAT_REKEY);
+ reauth = ike_sa->get_statistic(ike_sa, STAT_REAUTH);
+
if (rekey)
{
+ rekey -= now;
fprintf(out, ", rekeying in %V", &rekey);
}
if (reauth)
{
+ reauth -= now;
fprintf(out, ", %N reauthentication in %V", auth_class_names,
get_auth_class(ike_sa->get_peer_cfg(ike_sa)), &reauth);
}
@@ -107,13 +116,16 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
}
}
fprintf(out, "\n");
-
+
if (ike_proposal)
{
+ char buf[BUF_LEN];
+
+ snprintf(buf, BUF_LEN, "%P", ike_proposal);
fprintf(out, "%12s[%d]: IKE proposal: %s\n",
ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
- ike_proposal);
- }
+ buf+4);
+ }
}
}
@@ -123,68 +135,67 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
{
u_int32_t rekey, now = time(NULL);
- u_int32_t use_in, use_out, use_fwd;
- encryption_algorithm_t encr_alg;
- integrity_algorithm_t int_alg;
- size_t encr_len, int_len;
- ipsec_mode_t mode;
-
- child_sa->get_stats(child_sa, &mode, &encr_alg, &encr_len,
- &int_alg, &int_len, &rekey, &use_in, &use_out,
- &use_fwd);
+ u_int32_t use_in, use_out;
+ proposal_t *proposal;
+ child_cfg_t *config = child_sa->get_config(child_sa);
- fprintf(out, "%12s{%d}: %N, %N",
+ fprintf(out, "%12s{%d}: %N, %N%s",
child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
child_sa_state_names, child_sa->get_state(child_sa),
- ipsec_mode_names, mode);
+ ipsec_mode_names, child_sa->get_mode(child_sa),
+ config->use_proxy_mode(config) ? "_PROXY" : "");
if (child_sa->get_state(child_sa) == CHILD_INSTALLED)
{
- u_int16_t my_cpi = child_sa->get_cpi(child_sa, TRUE);
- u_int16_t other_cpi = child_sa->get_cpi(child_sa, FALSE);
-
- fprintf(out, ", %N SPIs: %.8x_i %.8x_o",
+ fprintf(out, ", %N%s SPIs: %.8x_i %.8x_o",
protocol_id_names, child_sa->get_protocol(child_sa),
+ child_sa->has_encap(child_sa) ? " in UDP" : "",
ntohl(child_sa->get_spi(child_sa, TRUE)),
ntohl(child_sa->get_spi(child_sa, FALSE)));
-
- /* Is IPCOMP activated ? */
- if (my_cpi && other_cpi)
+
+ if (child_sa->get_ipcomp(child_sa) != IPCOMP_NONE)
{
fprintf(out, ", IPCOMP CPIs: %.4x_i %.4x_o",
- ntohs(my_cpi), ntohs(other_cpi));
+ ntohs(child_sa->get_cpi(child_sa, TRUE)),
+ ntohs(child_sa->get_cpi(child_sa, FALSE)));
}
-
+
if (all)
{
fprintf(out, "\n%12s{%d}: ", child_sa->get_name(child_sa),
child_sa->get_reqid(child_sa));
-
- if (child_sa->get_protocol(child_sa) == PROTO_ESP)
+ proposal = child_sa->get_proposal(child_sa);
+ if (proposal)
{
- fprintf(out, "%N", encryption_algorithm_names, encr_alg);
+ u_int16_t encr_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED;
+ u_int16_t encr_size = 0, int_size = 0;
- if (encr_len)
+ proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
+ &encr_alg, &encr_size);
+ proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
+ &int_alg, &int_size);
+
+ if (encr_alg != ENCR_UNDEFINED)
{
- fprintf(out, "-%d", encr_len);
+ fprintf(out, "%N", encryption_algorithm_names, encr_alg);
+ if (encr_size)
+ {
+ fprintf(out, "-%d", encr_size);
+ }
}
if (int_alg != AUTH_UNDEFINED)
{
- fprintf(out, "/");
- }
- }
-
- if (int_alg != AUTH_UNDEFINED)
- {
- fprintf(out, "%N", integrity_algorithm_names, int_alg);
- if (int_len)
- {
- fprintf(out, "-%d", int_len);
+ fprintf(out, "/%N", integrity_algorithm_names, int_alg);
+ if (int_size)
+ {
+ fprintf(out, "-%d", int_size);
+ }
}
}
fprintf(out, ", rekeying ");
+ rekey = child_sa->get_lifetime(child_sa, FALSE);
if (rekey)
{
fprintf(out, "in %#V", &now, &rekey);
@@ -195,7 +206,7 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
}
fprintf(out, ", last use: ");
- use_in = max(use_in, use_fwd);
+ use_in = child_sa->get_usetime(child_sa, TRUE);
if (use_in)
{
fprintf(out, "%ds_i ", now - use_in);
@@ -204,6 +215,7 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
{
fprintf(out, "no_i ");
}
+ use_out = child_sa->get_usetime(child_sa, FALSE);
if (use_out)
{
fprintf(out, "%ds_o ", now - use_out);
diff --git a/src/charon/plugins/stroke/stroke_socket.c b/src/charon/plugins/stroke/stroke_socket.c
index 175322aa8..8c4ab7804 100644
--- a/src/charon/plugins/stroke/stroke_socket.c
+++ b/src/charon/plugins/stroke/stroke_socket.c
@@ -25,6 +25,7 @@
#include <sys/fcntl.h>
#include <unistd.h>
#include <errno.h>
+#include <pthread.h>
#include <processing/jobs/callback_job.h>
#include <daemon.h>
@@ -336,9 +337,9 @@ static void stroke_purge(private_stroke_socket_t *this,
CERT_X509_OCSP_RESPONSE);
}
-signal_t get_signal_from_logtype(char *type)
+debug_t get_group_from_name(char *type)
{
- if (strcasecmp(type, "any") == 0) return SIG_ANY;
+ if (strcasecmp(type, "any") == 0) return DBG_ANY;
else if (strcasecmp(type, "mgr") == 0) return DBG_MGR;
else if (strcasecmp(type, "ike") == 0) return DBG_IKE;
else if (strcasecmp(type, "chd") == 0) return DBG_CHD;
@@ -354,29 +355,44 @@ signal_t get_signal_from_logtype(char *type)
/**
* set the verbosity debug output
*/
-static void stroke_loglevel(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
+static void stroke_loglevel(private_stroke_socket_t *this,
+ stroke_msg_t *msg, FILE *out)
{
- signal_t signal;
+ enumerator_t *enumerator;
+ sys_logger_t *sys_logger;
+ file_logger_t *file_logger;
+ debug_t group;
pop_string(msg, &(msg->loglevel.type));
DBG1(DBG_CFG, "received stroke: loglevel %d for %s",
msg->loglevel.level, msg->loglevel.type);
- signal = get_signal_from_logtype(msg->loglevel.type);
- if (signal < 0)
+ group = get_group_from_name(msg->loglevel.type);
+ if (group < 0)
{
fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
return;
}
-
- charon->outlog->set_level(charon->outlog, signal, msg->loglevel.level);
- charon->syslog->set_level(charon->syslog, signal, msg->loglevel.level);
+ /* we set the loglevel on ALL sys- and file-loggers */
+ enumerator = charon->sys_loggers->create_enumerator(charon->sys_loggers);
+ while (enumerator->enumerate(enumerator, &sys_logger))
+ {
+ sys_logger->set_level(sys_logger, group, msg->loglevel.level);
+ }
+ enumerator->destroy(enumerator);
+ enumerator = charon->file_loggers->create_enumerator(charon->file_loggers);
+ while (enumerator->enumerate(enumerator, &file_logger))
+ {
+ file_logger->set_level(file_logger, group, msg->loglevel.level);
+ }
+ enumerator->destroy(enumerator);
}
/**
* set various config options
*/
-static void stroke_config(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
+static void stroke_config(private_stroke_socket_t *this,
+ stroke_msg_t *msg, FILE *out)
{
this->cred->cachecrl(this->cred, msg->config.cachecrl);
}
diff --git a/src/charon/plugins/unit_tester/tests/test_pool.c b/src/charon/plugins/unit_tester/tests/test_pool.c
index 5d5295bea..40334335d 100644
--- a/src/charon/plugins/unit_tester/tests/test_pool.c
+++ b/src/charon/plugins/unit_tester/tests/test_pool.c
@@ -15,6 +15,7 @@
#include <sys/time.h>
#include <time.h>
+#include <pthread.h>
#include <library.h>
#include <daemon.h>
diff --git a/src/charon/plugins/updown/Makefile.am b/src/charon/plugins/updown/Makefile.am
new file mode 100644
index 000000000..de60d9fbf
--- /dev/null
+++ b/src/charon/plugins/updown/Makefile.am
@@ -0,0 +1,12 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
+
+AM_CFLAGS = -rdynamic
+
+plugin_LTLIBRARIES = libstrongswan-updown.la
+libstrongswan_updown_la_SOURCES = \
+ updown_plugin.h updown_plugin.c \
+ updown_listener.h updown_listener.c
+libstrongswan_updown_la_LDFLAGS = -module
+
+
diff --git a/src/charon/plugins/updown/Makefile.in b/src/charon/plugins/updown/Makefile.in
new file mode 100644
index 000000000..603000a09
--- /dev/null
+++ b/src/charon/plugins/updown/Makefile.in
@@ -0,0 +1,501 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/charon/plugins/updown
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(plugindir)"
+pluginLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+libstrongswan_updown_la_LIBADD =
+am_libstrongswan_updown_la_OBJECTS = updown_plugin.lo \
+ updown_listener.lo
+libstrongswan_updown_la_OBJECTS = \
+ $(am_libstrongswan_updown_la_OBJECTS)
+libstrongswan_updown_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_updown_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_updown_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_updown_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IPSEC_ROUTING_TABLE = @IPSEC_ROUTING_TABLE@
+IPSEC_ROUTING_TABLE_PRIO = @IPSEC_ROUTING_TABLE_PRIO@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LINUX_HEADERS = @LINUX_HEADERS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+confdir = @confdir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libstrongswan_plugins = @libstrongswan_plugins@
+linuxdir = @linuxdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+resolv_conf = @resolv_conf@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+simreader = @simreader@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
+AM_CFLAGS = -rdynamic
+plugin_LTLIBRARIES = libstrongswan-updown.la
+libstrongswan_updown_la_SOURCES = \
+ updown_plugin.h updown_plugin.c \
+ updown_listener.h updown_listener.c
+
+libstrongswan_updown_la_LDFLAGS = -module
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/charon/plugins/updown/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/charon/plugins/updown/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-updown.la: $(libstrongswan_updown_la_OBJECTS) $(libstrongswan_updown_la_DEPENDENCIES)
+ $(libstrongswan_updown_la_LINK) -rpath $(plugindir) $(libstrongswan_updown_la_OBJECTS) $(libstrongswan_updown_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/updown_listener.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/updown_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+
+# 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/charon/plugins/updown/updown_listener.c b/src/charon/plugins/updown/updown_listener.c
new file mode 100644
index 000000000..7dfb874cb
--- /dev/null
+++ b/src/charon/plugins/updown/updown_listener.c
@@ -0,0 +1,320 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+
+#include "updown_listener.h"
+
+#include <daemon.h>
+#include <config/child_cfg.h>
+
+typedef struct private_updown_listener_t private_updown_listener_t;
+
+/**
+ * Private data of an updown_listener_t object.
+ */
+struct private_updown_listener_t {
+
+ /**
+ * Public updown_listener_t interface.
+ */
+ updown_listener_t public;
+
+ /**
+ * List of cached interface names
+ */
+ linked_list_t *iface_cache;
+};
+
+typedef struct cache_entry_t cache_entry_t;
+
+/**
+ * Cache line in the interface name cache.
+ */
+struct cache_entry_t {
+ /** requid of the CHILD_SA */
+ u_int32_t reqid;
+ /** cached interface name */
+ char *iface;
+};
+
+/**
+ * Insert an interface name to the cache
+ */
+static void cache_iface(private_updown_listener_t *this, u_int32_t reqid,
+ char *iface)
+{
+ cache_entry_t *entry = malloc_thing(cache_entry_t);
+
+ entry->reqid = reqid;
+ entry->iface = strdup(iface);
+
+ this->iface_cache->insert_first(this->iface_cache, entry);
+}
+
+/**
+ * Remove a cached interface name and return it.
+ */
+static char* uncache_iface(private_updown_listener_t *this, u_int32_t reqid)
+{
+ enumerator_t *enumerator;
+ cache_entry_t *entry;
+ char *iface = NULL;
+
+ enumerator = this->iface_cache->create_enumerator(this->iface_cache);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->reqid == reqid)
+ {
+ this->iface_cache->remove_at(this->iface_cache, enumerator);
+ iface = entry->iface;
+ free(entry);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return iface;
+}
+
+/**
+ * Run the up/down script
+ */
+static void updown(private_updown_listener_t *this, ike_sa_t *ike_sa,
+ child_sa_t *child_sa, bool up)
+{
+ traffic_selector_t *my_ts, *other_ts;
+ enumerator_t *enumerator;
+ child_cfg_t *config;
+ host_t *vip, *me, *other;
+ char *script;
+
+ config = child_sa->get_config(child_sa);
+ vip = ike_sa->get_virtual_ip(ike_sa, TRUE);
+ script = config->get_updown(config);
+ me = ike_sa->get_my_host(ike_sa);
+ other = ike_sa->get_other_host(ike_sa);
+
+ if (script == NULL)
+ {
+ return;
+ }
+
+ enumerator = child_sa->create_policy_enumerator(child_sa);
+ while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
+ {
+ char command[1024];
+ char *my_client, *other_client, *my_client_mask, *other_client_mask;
+ char *pos, *virtual_ip, *iface;
+ FILE *shell;
+
+ /* get subnet/bits from string */
+ if (asprintf(&my_client, "%R", my_ts) < 0)
+ {
+ my_client = NULL;
+ }
+ pos = strchr(my_client, '/');
+ *pos = '\0';
+ my_client_mask = pos + 1;
+ pos = strchr(my_client_mask, '[');
+ if (pos)
+ {
+ *pos = '\0';
+ }
+ if (asprintf(&other_client, "%R", other_ts) < 0)
+ {
+ other_client = NULL;
+ }
+ pos = strchr(other_client, '/');
+ *pos = '\0';
+ other_client_mask = pos + 1;
+ pos = strchr(other_client_mask, '[');
+ if (pos)
+ {
+ *pos = '\0';
+ }
+
+ if (vip)
+ {
+ if (asprintf(&virtual_ip, "PLUTO_MY_SOURCEIP='%H' ", vip) < 0)
+ {
+ virtual_ip = NULL;
+ }
+ }
+ else
+ {
+ if (asprintf(&virtual_ip, "") < 0)
+ {
+ virtual_ip = NULL;
+ }
+ }
+
+ if (up)
+ {
+ iface = charon->kernel_interface->get_interface(
+ charon->kernel_interface, me);
+ if (iface)
+ {
+ cache_iface(this, child_sa->get_reqid(child_sa), iface);
+ }
+ }
+ else
+ {
+ iface = uncache_iface(this, child_sa->get_reqid(child_sa));
+ }
+
+ /* build the command with all env variables.
+ * TODO: PLUTO_PEER_CA and PLUTO_NEXT_HOP are currently missing
+ */
+ snprintf(command, sizeof(command),
+ "2>&1 "
+ "PLUTO_VERSION='1.1' "
+ "PLUTO_VERB='%s%s%s' "
+ "PLUTO_CONNECTION='%s' "
+ "PLUTO_INTERFACE='%s' "
+ "PLUTO_REQID='%u' "
+ "PLUTO_ME='%H' "
+ "PLUTO_MY_ID='%D' "
+ "PLUTO_MY_CLIENT='%s/%s' "
+ "PLUTO_MY_CLIENT_NET='%s' "
+ "PLUTO_MY_CLIENT_MASK='%s' "
+ "PLUTO_MY_PORT='%u' "
+ "PLUTO_MY_PROTOCOL='%u' "
+ "PLUTO_PEER='%H' "
+ "PLUTO_PEER_ID='%D' "
+ "PLUTO_PEER_CLIENT='%s/%s' "
+ "PLUTO_PEER_CLIENT_NET='%s' "
+ "PLUTO_PEER_CLIENT_MASK='%s' "
+ "PLUTO_PEER_PORT='%u' "
+ "PLUTO_PEER_PROTOCOL='%u' "
+ "%s"
+ "%s"
+ "%s",
+ up ? "up" : "down",
+ my_ts->is_host(my_ts, me) ? "-host" : "-client",
+ me->get_family(me) == AF_INET ? "" : "-v6",
+ config->get_name(config),
+ iface ? iface : "unknown",
+ child_sa->get_reqid(child_sa),
+ me, ike_sa->get_my_id(ike_sa),
+ my_client, my_client_mask,
+ my_client, my_client_mask,
+ my_ts->get_from_port(my_ts),
+ my_ts->get_protocol(my_ts),
+ other, ike_sa->get_other_id(ike_sa),
+ other_client, other_client_mask,
+ other_client, other_client_mask,
+ other_ts->get_from_port(other_ts),
+ other_ts->get_protocol(other_ts),
+ virtual_ip,
+ config->get_hostaccess(config) ? "PLUTO_HOST_ACCESS='1' " : "",
+ script);
+ free(my_client);
+ free(other_client);
+ free(virtual_ip);
+ free(iface);
+
+ DBG3(DBG_CHD, "running updown script: %s", command);
+ shell = popen(command, "r");
+
+ if (shell == NULL)
+ {
+ DBG1(DBG_CHD, "could not execute updown script '%s'", script);
+ return;
+ }
+
+ while (TRUE)
+ {
+ char resp[128];
+
+ if (fgets(resp, sizeof(resp), shell) == NULL)
+ {
+ if (ferror(shell))
+ {
+ DBG1(DBG_CHD, "error reading output from updown script");
+ return;
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ char *e = resp + strlen(resp);
+ if (e > resp && e[-1] == '\n')
+ { /* trim trailing '\n' */
+ e[-1] = '\0';
+ }
+ DBG1(DBG_CHD, "updown: %s", resp);
+ }
+ }
+ pclose(shell);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Listener implementation
+ */
+static bool child_state_change(private_updown_listener_t *this, ike_sa_t *ike_sa,
+ child_sa_t *child_sa, child_sa_state_t state)
+{
+ child_sa_state_t old;
+
+ if (ike_sa)
+ {
+ old = child_sa->get_state(child_sa);
+
+ if ((old == CHILD_INSTALLED && state != CHILD_REKEYING ) ||
+ (old == CHILD_DELETING && state == CHILD_DESTROYING))
+ {
+ updown(this, ike_sa, child_sa, FALSE);
+ }
+ else if (state == CHILD_INSTALLED)
+ {
+ updown(this, ike_sa, child_sa, TRUE);
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of updown_listener_t.destroy.
+ */
+static void destroy(private_updown_listener_t *this)
+{
+ this->iface_cache->destroy(this->iface_cache);
+ free(this);
+}
+
+/**
+ * See header
+ */
+updown_listener_t *updown_listener_create()
+{
+ private_updown_listener_t *this = malloc_thing(private_updown_listener_t);
+
+ memset(&this->public.listener, 0, sizeof(listener_t));
+ this->public.listener.child_state_change = (void*)child_state_change;
+ this->public.destroy = (void(*)(updown_listener_t*))destroy;
+
+ this->iface_cache = linked_list_create();
+
+ return &this->public;
+}
+
diff --git a/src/charon/plugins/updown/updown_listener.h b/src/charon/plugins/updown/updown_listener.h
new file mode 100644
index 000000000..569d5817e
--- /dev/null
+++ b/src/charon/plugins/updown/updown_listener.h
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+/**
+ * @defgroup updown_listener updown_listener
+ * @{ @ingroup updown
+ */
+
+#ifndef UPDOWN_LISTENER_H_
+#define UPDOWN_LISTENER_H_
+
+#include <bus/bus.h>
+
+typedef struct updown_listener_t updown_listener_t;
+
+/**
+ * Listener which invokes the scripts on CHILD_SA up/down.
+ */
+struct updown_listener_t {
+
+ /**
+ * Implements listener_t.
+ */
+ listener_t listener;
+
+ /**
+ * Destroy a updown_listener_t.
+ */
+ void (*destroy)(updown_listener_t *this);
+};
+
+/**
+ * Create a updown_listener instance.
+ */
+updown_listener_t *updown_listener_create();
+
+#endif /* UPDOWN_LISTENER_ @}*/
diff --git a/src/charon/plugins/updown/updown_plugin.c b/src/charon/plugins/updown/updown_plugin.c
new file mode 100644
index 000000000..2e5884222
--- /dev/null
+++ b/src/charon/plugins/updown/updown_plugin.c
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#include "updown_plugin.h"
+#include "updown_listener.h"
+
+#include <daemon.h>
+
+typedef struct private_updown_plugin_t private_updown_plugin_t;
+
+/**
+ * private data of updown plugin
+ */
+struct private_updown_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ updown_plugin_t public;
+
+ /**
+ * Listener interface, listens to CHILD_SA state changes
+ */
+ updown_listener_t *listener;
+};
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_updown_plugin_t *this)
+{
+ charon->bus->remove_listener(charon->bus, &this->listener->listener);
+ this->listener->destroy(this->listener);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *plugin_create()
+{
+ private_updown_plugin_t *this = malloc_thing(private_updown_plugin_t);
+
+ this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+
+ this->listener = updown_listener_create();
+ charon->bus->add_listener(charon->bus, &this->listener->listener);
+
+ return &this->public.plugin;
+}
+
diff --git a/src/charon/plugins/updown/updown_plugin.h b/src/charon/plugins/updown/updown_plugin.h
new file mode 100644
index 000000000..4d0a930c2
--- /dev/null
+++ b/src/charon/plugins/updown/updown_plugin.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+/**
+ * @defgroup updown updown
+ * @ingroup cplugins
+ *
+ * @defgroup updown_plugin updown_plugin
+ * @{ @ingroup updown
+ */
+
+#ifndef UPDOWN_PLUGIN_H_
+#define UPDOWN_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct updown_plugin_t updown_plugin_t;
+
+/**
+ * Updown firewall script invocation plugin, compatible to pluto ones.
+ */
+struct updown_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+/**
+ * Create a updown_plugin instance.
+ */
+plugin_t *plugin_create();
+
+#endif /* UPDOWN_PLUGIN_H_ @}*/
diff --git a/src/charon/processing/jobs/acquire_job.c b/src/charon/processing/jobs/acquire_job.c
index b39e8e680..50cebd88a 100644
--- a/src/charon/processing/jobs/acquire_job.c
+++ b/src/charon/processing/jobs/acquire_job.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: acquire_job.c 3589 2008-03-13 14:14:44Z martin $
+ * $Id: acquire_job.c 4535 2008-10-31 01:43:23Z andreas $
*/
#include "acquire_job.h"
@@ -35,6 +35,16 @@ struct private_acquire_job_t {
* reqid of the child to rekey
*/
u_int32_t reqid;
+
+ /**
+ * acquired source traffic selector
+ */
+ traffic_selector_t *src_ts;
+
+ /**
+ * acquired destination traffic selector
+ */
+ traffic_selector_t *dst_ts;
};
/**
@@ -42,6 +52,8 @@ struct private_acquire_job_t {
*/
static void destroy(private_acquire_job_t *this)
{
+ DESTROY_IF(this->src_ts);
+ DESTROY_IF(this->dst_ts);
free(this);
}
@@ -50,13 +62,16 @@ static void destroy(private_acquire_job_t *this)
*/
static void execute(private_acquire_job_t *this)
{
- ike_sa_t *ike_sa;
+ ike_sa_t *ike_sa = NULL;
- ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
- this->reqid, TRUE);
+ if (this->reqid)
+ {
+ ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+ this->reqid, TRUE);
+ }
if (ike_sa == NULL)
{
- DBG2(DBG_JOB, "CHILD_SA with reqid %d not found for acquiring",
+ DBG1(DBG_JOB, "acquire job found no CHILD_SA with reqid {%d}",
this->reqid);
}
else
@@ -71,7 +86,9 @@ static void execute(private_acquire_job_t *this)
/*
* Described in header
*/
-acquire_job_t *acquire_job_create(u_int32_t reqid)
+acquire_job_t *acquire_job_create(u_int32_t reqid,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts)
{
private_acquire_job_t *this = malloc_thing(private_acquire_job_t);
@@ -81,6 +98,8 @@ acquire_job_t *acquire_job_create(u_int32_t reqid)
/* private variables */
this->reqid = reqid;
+ this->src_ts = src_ts;
+ this->dst_ts = dst_ts;
return &this->public;
}
diff --git a/src/charon/processing/jobs/acquire_job.h b/src/charon/processing/jobs/acquire_job.h
index 17c993d8e..7459ccc21 100644
--- a/src/charon/processing/jobs/acquire_job.h
+++ b/src/charon/processing/jobs/acquire_job.h
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: acquire_job.h 3589 2008-03-13 14:14:44Z martin $
+ * $Id: acquire_job.h 4535 2008-10-31 01:43:23Z andreas $
*/
/**
@@ -26,6 +26,7 @@
typedef struct acquire_job_t acquire_job_t;
#include <library.h>
+#include <config/traffic_selector.h>
#include <processing/jobs/job.h>
/**
@@ -46,8 +47,12 @@ struct acquire_job_t {
* We use the reqid to find the routed CHILD_SA.
*
* @param reqid reqid of the CHILD_SA to acquire
+ * @param src_ts source traffic selector
+ * @param dst_ts destination traffic selector
* @return acquire_job_t object
*/
-acquire_job_t *acquire_job_create(u_int32_t reqid);
+acquire_job_t *acquire_job_create(u_int32_t reqid,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts);
#endif /* REKEY_CHILD_SA_JOB_H_ @} */
diff --git a/src/charon/processing/jobs/callback_job.c b/src/charon/processing/jobs/callback_job.c
index e8892ee82..f0cebd473 100644
--- a/src/charon/processing/jobs/callback_job.c
+++ b/src/charon/processing/jobs/callback_job.c
@@ -12,12 +12,15 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: callback_job.c 3742 2008-04-03 09:19:12Z tobias $
+ * $Id: callback_job.c 4579 2008-11-05 11:29:56Z martin $
*/
#include "callback_job.h"
+#include <pthread.h>
+
#include <daemon.h>
+#include <utils/mutex.h>
typedef struct private_callback_job_t private_callback_job_t;
@@ -49,12 +52,12 @@ struct private_callback_job_t {
* thread ID of the job, if running
*/
pthread_t thread;
-
+
/**
* mutex to access jobs interna
*/
- pthread_mutex_t mutex;
-
+ mutex_t *mutex;
+
/**
* list of asociated child jobs
*/
@@ -76,6 +79,7 @@ static void destroy(private_callback_job_t *this)
this->cleanup(this->data);
}
this->children->destroy(this->children);
+ this->mutex->destroy(this->mutex);
free(this);
}
@@ -89,7 +93,7 @@ static void unregister(private_callback_job_t *this)
iterator_t *iterator;
private_callback_job_t *child;
- pthread_mutex_lock(&this->parent->mutex);
+ this->parent->mutex->lock(this->parent->mutex);
iterator = this->parent->children->create_iterator(this->parent->children, TRUE);
while (iterator->iterate(iterator, (void**)&child))
{
@@ -100,7 +104,7 @@ static void unregister(private_callback_job_t *this)
}
}
iterator->destroy(iterator);
- pthread_mutex_unlock(&this->parent->mutex);
+ this->parent->mutex->unlock(this->parent->mutex);
}
}
@@ -111,12 +115,12 @@ static void cancel(private_callback_job_t *this)
{
pthread_t thread;
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
thread = this->thread;
/* terminate its children */
this->children->invoke_offset(this->children, offsetof(callback_job_t, cancel));
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
/* terminate thread */
if (thread)
@@ -133,9 +137,9 @@ static void execute(private_callback_job_t *this)
{
bool cleanup = FALSE;
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
this->thread = pthread_self();
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
pthread_cleanup_push((void*)destroy, this);
while (TRUE)
@@ -180,7 +184,7 @@ callback_job_t *callback_job_create(callback_job_cb_t cb, void *data,
this->public.cancel = (void(*)(callback_job_t*))cancel;
/* private variables */
- pthread_mutex_init(&this->mutex, NULL);
+ this->mutex = mutex_create(MUTEX_DEFAULT);
this->callback = cb;
this->data = data;
this->cleanup = cleanup;
@@ -191,9 +195,9 @@ callback_job_t *callback_job_create(callback_job_cb_t cb, void *data,
/* register us at parent */
if (parent)
{
- pthread_mutex_lock(&this->parent->mutex);
+ this->parent->mutex->lock(this->parent->mutex);
this->parent->children->insert_last(this->parent->children, this);
- pthread_mutex_unlock(&this->parent->mutex);
+ this->parent->mutex->unlock(this->parent->mutex);
}
return &this->public;
diff --git a/src/charon/processing/jobs/initiate_mediation_job.c b/src/charon/processing/jobs/initiate_mediation_job.c
index ee9644045..4d4fd8dc6 100644
--- a/src/charon/processing/jobs/initiate_mediation_job.c
+++ b/src/charon/processing/jobs/initiate_mediation_job.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: initiate_mediation_job.c 4192 2008-07-18 15:51:40Z martin $
+ * $Id: initiate_mediation_job.c 4625 2008-11-11 13:12:05Z tobias $
*/
#include "initiate_mediation_job.h"
@@ -57,15 +57,13 @@ static void destroy(private_initiate_mediation_job_t *this)
* Callback to handle initiation of mediation connection
*/
static bool initiate_callback(private_initiate_mediation_job_t *this,
- signal_t signal, level_t level, ike_sa_t *ike_sa,
- void *data, char *format, va_list args)
+ debug_t group, level_t level, ike_sa_t *ike_sa,
+ char *format, va_list args)
{
- if (signal == CHD_UP_SUCCESS)
+ if (ike_sa && !this->mediation_sa_id)
{
- /* mediation connection is up */
this->mediation_sa_id = ike_sa->get_id(ike_sa);
this->mediation_sa_id = this->mediation_sa_id->clone(this->mediation_sa_id);
- return FALSE;
}
return TRUE;
}
@@ -74,16 +72,15 @@ static bool initiate_callback(private_initiate_mediation_job_t *this,
* Implementation of job_t.execute.
*/
static void initiate(private_initiate_mediation_job_t *this)
-{ /* FIXME: check the logging */
+{
ike_sa_t *mediated_sa, *mediation_sa;
peer_cfg_t *mediated_cfg, *mediation_cfg;
mediated_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
- this->mediated_sa_id);
+ this->mediated_sa_id);
if (mediated_sa)
{
mediated_cfg = mediated_sa->get_peer_cfg(mediated_sa);
- /* get_peer_cfg returns an internal object */
mediated_cfg->get_ref(mediated_cfg);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, mediated_sa);
@@ -98,29 +95,35 @@ static void initiate(private_initiate_mediation_job_t *this)
{
mediated_cfg->destroy(mediated_cfg);
mediation_cfg->destroy(mediation_cfg);
- /* this pointer should still be valid */
- charon->bus->set_sa(charon->bus, mediated_sa);
- DBG1(DBG_IKE, "mediation with the same peer is already in progress, queued");
+
+ mediated_sa = charon->ike_sa_manager->checkout(
+ charon->ike_sa_manager, this->mediated_sa_id);
+ if (mediated_sa)
+ {
+ DBG1(DBG_IKE, "mediation with the same peer is already in "
+ "progress, queued");
+ charon->ike_sa_manager->checkin(
+ charon->ike_sa_manager, mediated_sa);
+ }
destroy(this);
return;
}
/* we need an additional reference because initiate consumes one */
mediation_cfg->get_ref(mediation_cfg);
- /* this function call blocks until the connection is up or failed
- * we do not check the status, but NEED_MORE would be returned on success
- * because the registered callback returns FALSE then
- * this->mediation_sa_id is set in the callback */
- charon->controller->initiate(charon->controller,
- mediation_cfg, NULL, (controller_cb_t)initiate_callback, this);
- if (!this->mediation_sa_id)
+ if (charon->controller->initiate(charon->controller, mediation_cfg,
+ NULL, (controller_cb_t)initiate_callback, this) != SUCCESS)
{
- DBG1(DBG_JOB, "initiating mediation connection '%s' failed",
- mediation_cfg->get_name(mediation_cfg));
mediation_cfg->destroy(mediation_cfg);
mediated_cfg->destroy(mediated_cfg);
- charon->bus->set_sa(charon->bus, mediated_sa);
- SIG_IKE(UP_FAILED, "mediation failed");
+ mediated_sa = charon->ike_sa_manager->checkout(
+ charon->ike_sa_manager, this->mediated_sa_id);
+ if (mediated_sa)
+ {
+ DBG1(DBG_IKE, "initiating mediation connection failed");
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, mediated_sa);
+ }
destroy(this);
return;
}
@@ -131,15 +134,20 @@ static void initiate(private_initiate_mediation_job_t *this)
if (mediation_sa)
{
- if (mediation_sa->initiate_mediation(mediation_sa, mediated_cfg) != SUCCESS)
+ if (mediation_sa->initiate_mediation(mediation_sa,
+ mediated_cfg) != SUCCESS)
{
- DBG1(DBG_JOB, "initiating mediated connection '%s' failed",
- mediated_cfg->get_name(mediated_cfg));
mediated_cfg->destroy(mediated_cfg);
- charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, mediation_sa);
-
- charon->bus->set_sa(charon->bus, mediated_sa);
- SIG_IKE(UP_FAILED, "mediation failed");
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, mediation_sa);
+ mediated_sa = charon->ike_sa_manager->checkout(
+ charon->ike_sa_manager, this->mediated_sa_id);
+ if (mediated_sa)
+ {
+ DBG1(DBG_IKE, "establishing mediation connection failed");
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, mediated_sa);
+ }
destroy(this);
return;
}
@@ -156,7 +164,7 @@ static void initiate(private_initiate_mediation_job_t *this)
* Implementation of job_t.execute.
*/
static void reinitiate(private_initiate_mediation_job_t *this)
-{ /* FIXME: check the logging */
+{
ike_sa_t *mediated_sa, *mediation_sa;
peer_cfg_t *mediated_cfg;
@@ -178,13 +186,17 @@ static void reinitiate(private_initiate_mediation_job_t *this)
mediated_cfg->get_name(mediated_cfg));
mediated_cfg->destroy(mediated_cfg);
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, mediation_sa);
-
- charon->bus->set_sa(charon->bus, mediated_sa);
- SIG_IKE(UP_FAILED, "mediation failed");
+ mediated_sa = charon->ike_sa_manager->checkout(
+ charon->ike_sa_manager, this->mediated_sa_id);
+ if (mediated_sa)
+ {
+ DBG1(DBG_IKE, "establishing mediation connection failed");
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, mediated_sa);
+ }
destroy(this);
return;
}
-
charon->ike_sa_manager->checkin(charon->ike_sa_manager, mediation_sa);
}
diff --git a/src/charon/processing/jobs/migrate_job.c b/src/charon/processing/jobs/migrate_job.c
new file mode 100644
index 000000000..ec0a76fb9
--- /dev/null
+++ b/src/charon/processing/jobs/migrate_job.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2008 Andreas Steffen
+ * 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: migrate_job.c 4662 2008-11-16 21:19:58Z andreas $
+ */
+
+#include "migrate_job.h"
+
+#include <daemon.h>
+
+#include <config/child_cfg.h>
+
+
+typedef struct private_migrate_job_t private_migrate_job_t;
+
+/**
+ * Private data of a migrate_job_t object.
+ */
+struct private_migrate_job_t {
+ /**
+ * Public migrate_job_t interface.
+ */
+ migrate_job_t public;
+
+ /**
+ * reqid of the CHILD_SA if it already exists
+ */
+ u_int32_t reqid;
+
+ /**
+ * source traffic selector
+ */
+ traffic_selector_t *src_ts;
+
+ /**
+ * destination traffic selector
+ */
+ traffic_selector_t *dst_ts;
+
+ /**
+ * local host address to be used for IKE
+ */
+ host_t *local;
+
+ /**
+ * remote host address to be used for IKE
+ */
+ host_t *remote;
+};
+
+/**
+ * Implementation of job_t.destroy.
+ */
+static void destroy(private_migrate_job_t *this)
+{
+ DESTROY_IF(this->src_ts);
+ DESTROY_IF(this->dst_ts);
+ DESTROY_IF(this->local);
+ DESTROY_IF(this->remote);
+ free(this);
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static void execute(private_migrate_job_t *this)
+{
+ ike_sa_t *ike_sa = NULL;
+
+ if (this->reqid)
+ {
+ ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+ this->reqid, TRUE);
+ }
+ if (ike_sa)
+ {
+ iterator_t *children;
+ child_sa_t *child_sa;
+ host_t *host;
+
+ children = ike_sa->create_child_sa_iterator(ike_sa);
+ while (children->iterate(children, (void**)&child_sa))
+ {
+ if (child_sa->get_reqid(child_sa) == this->reqid)
+ {
+ break;
+ }
+ }
+ children->destroy(children);
+ DBG2(DBG_JOB, "found CHILD_SA with reqid {%d}", this->reqid);
+
+ ike_sa->set_kmaddress(ike_sa, this->local, this->remote);
+
+ host = this->local->clone(this->local);
+ host->set_port(host, IKEV2_UDP_PORT);
+ ike_sa->set_my_host(ike_sa, host);
+
+ host = this->remote->clone(this->remote);
+ host->set_port(host, IKEV2_UDP_PORT);
+ ike_sa->set_other_host(ike_sa, host);
+
+ if (child_sa->update_hosts(child_sa, this->local, this->remote,
+ ike_sa->get_virtual_ip(ike_sa, TRUE),
+ ike_sa->has_condition(ike_sa, COND_NAT_ANY)) == NOT_SUPPORTED)
+ {
+ ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE));
+ }
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ else
+ {
+ DBG1(DBG_JOB, "no CHILD_SA found with reqid {%d}", this->reqid);
+ }
+ destroy(this);
+}
+
+/*
+ * Described in header
+ */
+migrate_job_t *migrate_job_create(u_int32_t reqid,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t dir,
+ host_t *local, host_t *remote)
+{
+ private_migrate_job_t *this = malloc_thing(private_migrate_job_t);
+
+ /* interface functions */
+ this->public.job_interface.execute = (void (*) (job_t *)) execute;
+ this->public.job_interface.destroy = (void (*)(job_t*)) destroy;
+
+ /* private variables */
+ this->reqid = reqid;
+ this->src_ts = (dir == POLICY_OUT) ? src_ts : dst_ts;
+ this->dst_ts = (dir == POLICY_OUT) ? dst_ts : src_ts;
+ this->local = local;
+ this->remote = remote;
+
+ return &this->public;
+}
diff --git a/src/charon/processing/jobs/migrate_job.h b/src/charon/processing/jobs/migrate_job.h
new file mode 100644
index 000000000..a99ffbb0c
--- /dev/null
+++ b/src/charon/processing/jobs/migrate_job.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008 Andreas Steffen
+ * 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: migrate_job.h 4662 2008-11-16 21:19:58Z andreas $
+ */
+
+/**
+ * @defgroup migrate_job migrate_job
+ * @{ @ingroup jobs
+ */
+
+#ifndef MIGRATE_JOB_H_
+#define MIGRATE_JOB_H_
+
+typedef struct migrate_job_t migrate_job_t;
+
+#include <library.h>
+#include <utils/host.h>
+#include <config/traffic_selector.h>
+#include <kernel/kernel_ipsec.h>
+#include <processing/jobs/job.h>
+
+/**
+ * Class representing a MIGRATE Job.
+ *
+ * This job sets a routed CHILD_SA for an existing IPsec policy.
+ */
+struct migrate_job_t {
+ /**
+ * The job_t interface.
+ */
+ job_t job_interface;
+};
+
+/**
+ * Creates a job of type MIGRATE.
+ *
+ * We use the reqid or the traffic selectors to find a matching CHILD_SA.
+ *
+ * @param reqid reqid of the CHILD_SA to acquire
+ * @param src_ts source traffic selector to be used in the policy
+ * @param dst_ts destination traffic selector to be used in the policy
+ * @param dir direction of the policy (in|out)
+ * @param local local host address to be used in the IKE_SA
+ * @param remote remote host address to be used in the IKE_SA
+ * @return migrate_job_t object
+ */
+migrate_job_t *migrate_job_create(u_int32_t reqid,
+ traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts,
+ policy_dir_t dir,
+ host_t *local, host_t *remote);
+
+#endif /* MIGRATE_JOB_H_ @} */
diff --git a/src/charon/processing/processor.c b/src/charon/processing/processor.c
index 010f6624f..9cff090bf 100644
--- a/src/charon/processing/processor.c
+++ b/src/charon/processing/processor.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: processor.c 3742 2008-04-03 09:19:12Z tobias $
+ * $Id: processor.c 4579 2008-11-05 11:29:56Z martin $
*/
#include <stdlib.h>
@@ -24,6 +24,7 @@
#include "processor.h"
#include <daemon.h>
+#include <utils/mutex.h>
#include <utils/linked_list.h>
@@ -61,17 +62,17 @@ struct private_processor_t {
/**
* access to linked_list is locked through this mutex
*/
- pthread_mutex_t mutex;
+ mutex_t *mutex;
/**
* Condvar to wait for new jobs
*/
- pthread_cond_t jobadded;
+ condvar_t *job_added;
/**
* Condvar to wait for terminated threads
*/
- pthread_cond_t threadterminated;
+ condvar_t *thread_terminated;
};
static void process_jobs(private_processor_t *this);
@@ -85,10 +86,10 @@ static void restart(private_processor_t *this)
if (pthread_create(&thread, NULL, (void*)process_jobs, this) != 0)
{
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
this->total_threads--;
- pthread_cond_broadcast(&this->threadterminated);
- pthread_mutex_unlock(&this->mutex);
+ this->thread_terminated->broadcast(this->thread_terminated);
+ this->mutex->unlock(this->mutex);
}
}
@@ -103,7 +104,7 @@ static void process_jobs(private_processor_t *this)
DBG2(DBG_JOB, "started worker thread, thread_ID: %06u", (int)pthread_self());
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
while (this->desired_threads >= this->total_threads)
{
job_t *job;
@@ -111,21 +112,21 @@ static void process_jobs(private_processor_t *this)
if (this->list->get_count(this->list) == 0)
{
this->idle_threads++;
- pthread_cond_wait(&this->jobadded, &this->mutex);
+ this->job_added->wait(this->job_added, this->mutex);
this->idle_threads--;
continue;
}
this->list->remove_first(this->list, (void**)&job);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
/* terminated threads are restarted, so we have a constant pool */
pthread_cleanup_push((void*)restart, this);
job->execute(job);
pthread_cleanup_pop(0);
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
}
this->total_threads--;
- pthread_cond_signal(&this->threadterminated);
- pthread_mutex_unlock(&this->mutex);
+ this->thread_terminated->signal(this->thread_terminated);
+ this->mutex->unlock(this->mutex);
}
/**
@@ -134,9 +135,9 @@ static void process_jobs(private_processor_t *this)
static u_int get_total_threads(private_processor_t *this)
{
u_int count;
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
count = this->total_threads;
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
return count;
}
@@ -146,9 +147,9 @@ static u_int get_total_threads(private_processor_t *this)
static u_int get_idle_threads(private_processor_t *this)
{
u_int count;
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
count = this->idle_threads;
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
return count;
}
@@ -158,9 +159,9 @@ static u_int get_idle_threads(private_processor_t *this)
static u_int get_job_load(private_processor_t *this)
{
u_int load;
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
load = this->list->get_count(this->list);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
return load;
}
@@ -169,10 +170,10 @@ static u_int get_job_load(private_processor_t *this)
*/
static void queue_job(private_processor_t *this, job_t *job)
{
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
this->list->insert_last(this->list, job);
- pthread_cond_signal(&this->jobadded);
- pthread_mutex_unlock(&this->mutex);
+ this->job_added->signal(this->job_added);
+ this->mutex->unlock(this->mutex);
}
/**
@@ -180,7 +181,7 @@ static void queue_job(private_processor_t *this, job_t *job)
*/
static void set_threads(private_processor_t *this, u_int count)
{
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
if (count > this->total_threads)
{ /* increase thread count */
int i;
@@ -200,8 +201,8 @@ static void set_threads(private_processor_t *this, u_int count)
{ /* decrease thread count */
this->desired_threads = count;
}
- pthread_cond_broadcast(&this->jobadded);
- pthread_mutex_unlock(&this->mutex);
+ this->job_added->broadcast(this->job_added);
+ this->mutex->unlock(this->mutex);
}
/**
@@ -210,13 +211,16 @@ static void set_threads(private_processor_t *this, u_int count)
static void destroy(private_processor_t *this)
{
set_threads(this, 0);
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
while (this->total_threads > 0)
{
- pthread_cond_broadcast(&this->jobadded);
- pthread_cond_wait(&this->threadterminated, &this->mutex);
+ this->job_added->broadcast(this->job_added);
+ this->thread_terminated->wait(this->thread_terminated, this->mutex);
}
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
+ this->thread_terminated->destroy(this->thread_terminated);
+ this->job_added->destroy(this->job_added);
+ this->mutex->destroy(this->mutex);
this->list->destroy_offset(this->list, offsetof(job_t, destroy));
free(this);
}
@@ -236,9 +240,9 @@ processor_t *processor_create(size_t pool_size)
this->public.destroy = (void(*)(processor_t*))destroy;
this->list = linked_list_create();
- pthread_mutex_init(&this->mutex, NULL);
- pthread_cond_init(&this->jobadded, NULL);
- pthread_cond_init(&this->threadterminated, NULL);
+ this->mutex = mutex_create(MUTEX_DEFAULT);
+ this->job_added = condvar_create(CONDVAR_DEFAULT);
+ this->thread_terminated = condvar_create(CONDVAR_DEFAULT);
this->total_threads = 0;
this->desired_threads = 0;
this->idle_threads = 0;
diff --git a/src/charon/sa/authenticators/eap/eap_manager.c b/src/charon/sa/authenticators/eap/eap_manager.c
index 44d84156c..c1c2d6fce 100644
--- a/src/charon/sa/authenticators/eap/eap_manager.c
+++ b/src/charon/sa/authenticators/eap/eap_manager.c
@@ -12,14 +12,13 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: eap_manager.c 3589 2008-03-13 14:14:44Z martin $
+ * $Id: eap_manager.c 4579 2008-11-05 11:29:56Z martin $
*/
#include "eap_manager.h"
-#include <pthread.h>
-
#include <utils/linked_list.h>
+#include <utils/mutex.h>
typedef struct private_eap_manager_t private_eap_manager_t;
typedef struct eap_entry_t eap_entry_t;
@@ -68,7 +67,7 @@ struct private_eap_manager_t {
/**
* mutex to lock methods
*/
- pthread_mutex_t mutex;
+ mutex_t *mutex;
};
/**
@@ -85,9 +84,9 @@ static void add_method(private_eap_manager_t *this, eap_type_t type,
entry->role = role;
entry->constructor = constructor;
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
this->methods->insert_last(this->methods, entry);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
}
/**
@@ -98,7 +97,7 @@ static void remove_method(private_eap_manager_t *this, eap_constructor_t constru
enumerator_t *enumerator;
eap_entry_t *entry;
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
enumerator = this->methods->create_enumerator(this->methods);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -109,7 +108,7 @@ static void remove_method(private_eap_manager_t *this, eap_constructor_t constru
}
}
enumerator->destroy(enumerator);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
}
/**
@@ -124,7 +123,7 @@ static eap_method_t* create_instance(private_eap_manager_t *this,
eap_entry_t *entry;
eap_method_t *method = NULL;
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
enumerator = this->methods->create_enumerator(this->methods);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -139,7 +138,7 @@ static eap_method_t* create_instance(private_eap_manager_t *this,
}
}
enumerator->destroy(enumerator);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
return method;
}
@@ -149,6 +148,7 @@ static eap_method_t* create_instance(private_eap_manager_t *this,
static void destroy(private_eap_manager_t *this)
{
this->methods->destroy_function(this->methods, free);
+ this->mutex->destroy(this->mutex);
free(this);
}
@@ -165,7 +165,7 @@ eap_manager_t *eap_manager_create()
this->public.destroy = (void(*)(eap_manager_t*))destroy;
this->methods = linked_list_create();
- pthread_mutex_init(&this->mutex, NULL);
+ this->mutex = mutex_create(MUTEX_DEFAULT);
return &this->public;
}
diff --git a/src/charon/sa/authenticators/eap_authenticator.c b/src/charon/sa/authenticators/eap_authenticator.c
index 0909d6563..5c22f3df2 100644
--- a/src/charon/sa/authenticators/eap_authenticator.c
+++ b/src/charon/sa/authenticators/eap_authenticator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Martin Willi
+ * Copyright (C) 2006-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: eap_authenticator.c 4292 2008-08-26 19:54:47Z andreas $
+ * $Id: eap_authenticator.c 4495 2008-10-28 16:07:06Z martin $
*/
#include <string.h>
@@ -70,36 +70,24 @@ struct private_eap_authenticator_t {
*/
u_int32_t vendor;
};
-
-/**
- * reuse shared key signature function from PSK authenticator
- */
-extern chunk_t build_shared_key_signature(chunk_t ike_sa_init, chunk_t nonce,
- chunk_t secret, identification_t *id,
- chunk_t skp, prf_t *prf);
/**
* Implementation of authenticator_t.verify.
*/
static status_t verify(private_eap_authenticator_t *this, chunk_t ike_sa_init,
chunk_t my_nonce, auth_payload_t *auth_payload)
{
- chunk_t auth_data, recv_auth_data, secret;
- identification_t *other_id = this->ike_sa->get_other_id(this->ike_sa);
+ chunk_t auth_data, recv_auth_data;
+ identification_t *other_id;
+ keymat_t *keymat;
- if (this->msk.len)
- { /* use MSK if EAP method established one... */
- secret = this->msk;
- }
- else
- { /* ... or use SKp if not */
- secret = this->ike_sa->get_skp_verify(this->ike_sa);
- }
- auth_data = build_shared_key_signature(ike_sa_init, my_nonce, secret,
- other_id, this->ike_sa->get_skp_verify(this->ike_sa),
- this->ike_sa->get_prf(this->ike_sa));
+ other_id = this->ike_sa->get_other_id(this->ike_sa);
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+
+ auth_data = keymat->get_psk_sig(keymat, TRUE, ike_sa_init, my_nonce,
+ this->msk, other_id);
recv_auth_data = auth_payload->get_data(auth_payload);
- if (!chunk_equals(auth_data, recv_auth_data))
+ if (!auth_data.len || !chunk_equals(auth_data, recv_auth_data))
{
DBG1(DBG_IKE, "verification of AUTH payload created from EAP MSK failed");
chunk_free(&auth_data);
@@ -118,23 +106,18 @@ static status_t verify(private_eap_authenticator_t *this, chunk_t ike_sa_init,
static status_t build(private_eap_authenticator_t *this, chunk_t ike_sa_init,
chunk_t other_nonce, auth_payload_t **auth_payload)
{
- chunk_t auth_data, secret;
- identification_t *my_id = this->ike_sa->get_my_id(this->ike_sa);
+ identification_t *my_id;
+ chunk_t auth_data;
+ keymat_t *keymat;
+
+ my_id = this->ike_sa->get_my_id(this->ike_sa);
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
DBG1(DBG_IKE, "authentication of '%D' (myself) with %N",
my_id, auth_class_names, AUTH_CLASS_EAP);
-
- if (this->msk.len)
- { /* use MSK if EAP method established one... */
- secret = this->msk;
- }
- else
- { /* ... or use SKp if not */
- secret = this->ike_sa->get_skp_build(this->ike_sa);
- }
- auth_data = build_shared_key_signature(ike_sa_init, other_nonce, secret,
- my_id, this->ike_sa->get_skp_build(this->ike_sa),
- this->ike_sa->get_prf(this->ike_sa));
+
+ auth_data = keymat->get_psk_sig(keymat, FALSE, ike_sa_init, other_nonce,
+ this->msk, my_id);
*auth_payload = auth_payload_create();
(*auth_payload)->set_auth_method(*auth_payload, AUTH_PSK);
diff --git a/src/charon/sa/authenticators/psk_authenticator.c b/src/charon/sa/authenticators/psk_authenticator.c
index d003dc2c9..ae5a66479 100644
--- a/src/charon/sa/authenticators/psk_authenticator.c
+++ b/src/charon/sa/authenticators/psk_authenticator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: psk_authenticator.c 3589 2008-03-13 14:14:44Z martin $
+ * $Id: psk_authenticator.c 4495 2008-10-28 16:07:06Z martin $
*/
#include <string.h>
@@ -23,12 +23,6 @@
#include <daemon.h>
#include <credentials/auth_info.h>
-/**
- * Key pad for the AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
- */
-#define IKEV2_KEY_PAD "Key Pad for IKEv2"
-#define IKEV2_KEY_PAD_LENGTH 17
-
typedef struct private_psk_authenticator_t private_psk_authenticator_t;
@@ -49,55 +43,6 @@ struct private_psk_authenticator_t {
};
/**
- * Builds the octets to be signed as described in section 2.15 of RFC 4306
- */
-chunk_t build_tbs_octets(chunk_t ike_sa_init, chunk_t nonce,
- identification_t *id, prf_t *prf)
-{
- u_int8_t id_header_buf[] = {0x00, 0x00, 0x00, 0x00};
- chunk_t id_header = chunk_from_buf(id_header_buf);
- chunk_t id_with_header, id_prfd, id_encoding;
-
- id_header_buf[0] = id->get_type(id);
- id_encoding = id->get_encoding(id);
-
- id_with_header = chunk_cat("cc", id_header, id_encoding);
- prf->allocate_bytes(prf, id_with_header, &id_prfd);
- chunk_free(&id_with_header);
-
- return chunk_cat("ccm", ike_sa_init, nonce, id_prfd);
-}
-
-/**
- * Creates the AUTH data using auth method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
- */
-chunk_t build_shared_key_signature(chunk_t ike_sa_init, chunk_t nonce,
- chunk_t secret, identification_t *id,
- chunk_t skp, prf_t *prf)
-{
- chunk_t key_pad, key, auth_data, octets;
-
- prf->set_key(prf, skp);
- octets = build_tbs_octets(ike_sa_init, nonce, id, prf);
- /* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */
- key_pad.ptr = IKEV2_KEY_PAD;
- key_pad.len = IKEV2_KEY_PAD_LENGTH;
- prf->set_key(prf, secret);
- prf->allocate_bytes(prf, key_pad, &key);
- prf->set_key(prf, key);
- prf->allocate_bytes(prf, octets, &auth_data);
- DBG3(DBG_IKE, "octets = message + nonce + prf(Sk_px, IDx') %B", &octets);
- DBG3(DBG_IKE, "secret %B", &secret);
- DBG3(DBG_IKE, "keypad %B", &key_pad);
- DBG3(DBG_IKE, "prf(secret, keypad) %B", &key);
- DBG3(DBG_IKE, "AUTH = prf(prf(secret, keypad), octets) %B", &auth_data);
- chunk_free(&octets);
- chunk_free(&key);
-
- return auth_data;
-}
-
-/**
* Implementation of authenticator_t.verify.
*/
static status_t verify(private_psk_authenticator_t *this, chunk_t ike_sa_init,
@@ -105,25 +50,25 @@ static status_t verify(private_psk_authenticator_t *this, chunk_t ike_sa_init,
{
chunk_t auth_data, recv_auth_data;
identification_t *my_id, *other_id;
- shared_key_t *shared_key;
+ shared_key_t *key;
enumerator_t *enumerator;
bool authenticated = FALSE;
int keys_found = 0;
+ keymat_t *keymat;
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+ recv_auth_data = auth_payload->get_data(auth_payload);
my_id = this->ike_sa->get_my_id(this->ike_sa);
other_id = this->ike_sa->get_other_id(this->ike_sa);
enumerator = charon->credentials->create_shared_enumerator(
charon->credentials, SHARED_IKE, my_id, other_id);
- while (!authenticated && enumerator->enumerate(enumerator, &shared_key, NULL, NULL))
+ while (!authenticated && enumerator->enumerate(enumerator, &key, NULL, NULL))
{
keys_found++;
- auth_data = build_shared_key_signature(ike_sa_init, my_nonce,
- shared_key->get_key(shared_key), other_id,
- this->ike_sa->get_skp_verify(this->ike_sa),
- this->ike_sa->get_prf(this->ike_sa));
- recv_auth_data = auth_payload->get_data(auth_payload);
- if (auth_data.len == recv_auth_data.len &&
- memeq(auth_data.ptr, recv_auth_data.ptr, auth_data.len))
+
+ auth_data = keymat->get_psk_sig(keymat, TRUE, ike_sa_init, my_nonce,
+ key->get_key(key), other_id);
+ if (auth_data.len && chunk_equals(auth_data, recv_auth_data))
{
DBG1(DBG_IKE, "authentication of '%D' with %N successful",
other_id, auth_method_names, AUTH_PSK);
@@ -153,26 +98,26 @@ static status_t verify(private_psk_authenticator_t *this, chunk_t ike_sa_init,
static status_t build(private_psk_authenticator_t *this, chunk_t ike_sa_init,
chunk_t other_nonce, auth_payload_t **auth_payload)
{
- shared_key_t *shared_key;
- chunk_t auth_data;
identification_t *my_id, *other_id;
+ shared_key_t *key;
+ chunk_t auth_data;
+ keymat_t *keymat;
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
my_id = this->ike_sa->get_my_id(this->ike_sa);
other_id = this->ike_sa->get_other_id(this->ike_sa);
DBG1(DBG_IKE, "authentication of '%D' (myself) with %N",
my_id, auth_method_names, AUTH_PSK);
- shared_key = charon->credentials->get_shared(charon->credentials, SHARED_IKE,
- my_id, other_id);
- if (shared_key == NULL)
+ key = charon->credentials->get_shared(charon->credentials, SHARED_IKE,
+ my_id, other_id);
+ if (key == NULL)
{
DBG1(DBG_IKE, "no shared key found for '%D' - '%D'", my_id, other_id);
return NOT_FOUND;
}
- auth_data = build_shared_key_signature(ike_sa_init, other_nonce,
- shared_key->get_key(shared_key), my_id,
- this->ike_sa->get_skp_build(this->ike_sa),
- this->ike_sa->get_prf(this->ike_sa));
- shared_key->destroy(shared_key);
+ auth_data = keymat->get_psk_sig(keymat, FALSE, ike_sa_init, other_nonce,
+ key->get_key(key), my_id);
+ key->destroy(key);
DBG2(DBG_IKE, "successfully created shared key MAC");
*auth_payload = auth_payload_create();
(*auth_payload)->set_auth_method(*auth_payload, AUTH_PSK);
diff --git a/src/charon/sa/authenticators/pubkey_authenticator.c b/src/charon/sa/authenticators/pubkey_authenticator.c
index 2c02ca84c..c16f3b888 100644
--- a/src/charon/sa/authenticators/pubkey_authenticator.c
+++ b/src/charon/sa/authenticators/pubkey_authenticator.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 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: pubkey_authenticator.c 4054 2008-06-10 20:31:53Z andreas $
+ * $Id: pubkey_authenticator.c 4495 2008-10-28 16:07:06Z martin $
*/
#include <string.h>
@@ -44,12 +44,6 @@ struct private_pubkey_authenticator_t {
};
/**
- * Function implemented in psk_authenticator.c
- */
-extern chunk_t build_tbs_octets(chunk_t ike_sa_init, chunk_t nonce,
- identification_t *id, prf_t *prf);
-
-/**
* Implementation of authenticator_t.verify.
*/
static status_t verify(private_pubkey_authenticator_t *this, chunk_t ike_sa_init,
@@ -58,15 +52,15 @@ static status_t verify(private_pubkey_authenticator_t *this, chunk_t ike_sa_init
public_key_t *public;
auth_method_t auth_method;
chunk_t auth_data, octets;
- identification_t *other_id;
- prf_t *prf;
+ identification_t *id;
auth_info_t *auth, *current_auth;
enumerator_t *enumerator;
key_type_t key_type = KEY_ECDSA;
signature_scheme_t scheme;
status_t status = FAILED;
+ keymat_t *keymat;
- other_id = this->ike_sa->get_other_id(this->ike_sa);
+ id = this->ike_sa->get_other_id(this->ike_sa);
auth_method = auth_payload->get_auth_method(auth_payload);
switch (auth_method)
{
@@ -89,19 +83,17 @@ static status_t verify(private_pubkey_authenticator_t *this, chunk_t ike_sa_init
return INVALID_ARG;
}
auth_data = auth_payload->get_data(auth_payload);
- prf = this->ike_sa->get_prf(this->ike_sa);
- prf->set_key(prf, this->ike_sa->get_skp_verify(this->ike_sa));
- octets = build_tbs_octets(ike_sa_init, my_nonce, other_id, prf);
-
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+ octets = keymat->get_auth_octets(keymat, TRUE, ike_sa_init, my_nonce, id);
auth = this->ike_sa->get_other_auth(this->ike_sa);
enumerator = charon->credentials->create_public_enumerator(
- charon->credentials, key_type, other_id, auth);
+ charon->credentials, key_type, id, auth);
while (enumerator->enumerate(enumerator, &public, &current_auth))
{
if (public->verify(public, scheme, octets, auth_data))
{
DBG1(DBG_IKE, "authentication of '%D' with %N successful",
- other_id, auth_method_names, auth_method);
+ id, auth_method_names, auth_method);
status = SUCCESS;
auth->merge(auth, current_auth);
break;
@@ -125,19 +117,19 @@ static status_t build(private_pubkey_authenticator_t *this, chunk_t ike_sa_init,
chunk_t octets, auth_data;
status_t status = FAILED;
private_key_t *private;
- identification_t *my_id;
- prf_t *prf;
+ identification_t *id;
auth_info_t *auth;
auth_method_t auth_method;
signature_scheme_t scheme;
+ keymat_t *keymat;
- my_id = this->ike_sa->get_my_id(this->ike_sa);
+ id = this->ike_sa->get_my_id(this->ike_sa);
auth = this->ike_sa->get_my_auth(this->ike_sa);
private = charon->credentials->get_private(charon->credentials, KEY_ANY,
- my_id, auth);
+ id, auth);
if (private == NULL)
{
- DBG1(DBG_IKE, "no private key found for '%D'", my_id);
+ DBG1(DBG_IKE, "no private key found for '%D'", id);
return NOT_FOUND;
}
@@ -176,9 +168,8 @@ static status_t build(private_pubkey_authenticator_t *this, chunk_t ike_sa_init,
key_type_names, private->get_type(private));
return status;
}
- prf = this->ike_sa->get_prf(this->ike_sa);
- prf->set_key(prf, this->ike_sa->get_skp_build(this->ike_sa));
- octets = build_tbs_octets(ike_sa_init, other_nonce, my_id, prf);
+ keymat = this->ike_sa->get_keymat(this->ike_sa);
+ octets = keymat->get_auth_octets(keymat, FALSE, ike_sa_init, other_nonce, id);
if (private->sign(private, scheme, octets, &auth_data))
{
@@ -189,9 +180,9 @@ static status_t build(private_pubkey_authenticator_t *this, chunk_t ike_sa_init,
chunk_free(&auth_data);
status = SUCCESS;
}
- DBG1(DBG_IKE, "authentication of '%D' (myself) with %N %s", my_id,
- auth_method_names, auth_method,
- (status == SUCCESS)? "successful":"failed");
+ DBG1(DBG_IKE, "authentication of '%D' (myself) with %N %s", id,
+ auth_method_names, auth_method,
+ (status == SUCCESS)? "successful":"failed");
chunk_free(&octets);
private->destroy(private);
diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c
index 7c4b398cf..d7a63d5e8 100644
--- a/src/charon/sa/child_sa.c
+++ b/src/charon/sa/child_sa.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006-2008 Tobias Brunner
- * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -15,7 +15,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: child_sa.c 4358 2008-09-25 13:56:23Z tobias $
+ * $Id: child_sa.c 4665 2008-11-17 00:01:34Z andreas $
*/
#define _GNU_SOURCE
@@ -23,36 +23,21 @@
#include <stdio.h>
#include <string.h>
+#include <time.h>
#include <daemon.h>
-ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DELETING,
+ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
"CREATED",
"ROUTED",
+ "INSTALLING",
"INSTALLED",
+ "UPDATING",
"REKEYING",
"DELETING",
+ "DESTROYING",
);
-typedef struct sa_policy_t sa_policy_t;
-
-/**
- * Struct used to store information for a policy. This
- * is needed since we must provide all this information
- * for deleting a policy...
- */
-struct sa_policy_t {
- /**
- * Traffic selector for us
- */
- traffic_selector_t *my_ts;
-
- /**
- * Traffic selector for other
- */
- traffic_selector_t *other_ts;
-};
-
typedef struct private_child_sa_t private_child_sa_t;
/**
@@ -64,83 +49,77 @@ struct private_child_sa_t {
*/
child_sa_t public;
- struct {
- /** address of peer */
- host_t *addr;
- /** id of peer */
- identification_t *id;
- /** actual used SPI, 0 if unused */
- u_int32_t spi;
- /** Compression Parameter Index (CPI) used, 0 if unused */
- u_int16_t cpi;
- } me, other;
-
/**
- * Allocated SPI for a ESP proposal candidates
+ * address of us
*/
- u_int32_t alloc_esp_spi;
+ host_t *my_addr;
/**
- * Allocated SPI for a AH proposal candidates
+ * address of remote
*/
- u_int32_t alloc_ah_spi;
+ host_t *other_addr;
/**
- * Protocol used to protect this SA, ESP|AH
+ * our actually used SPI, 0 if unused
*/
- protocol_id_t protocol;
+ u_int32_t my_spi;
/**
- * List containing sa_policy_t objects
+ * others used SPI, 0 if unused
*/
- linked_list_t *policies;
+ u_int32_t other_spi;
/**
- * Seperate list for local traffic selectors
+ * our Compression Parameter Index (CPI) used, 0 if unused
*/
- linked_list_t *my_ts;
+ u_int16_t my_cpi;
/**
- * Seperate list for remote traffic selectors
+ * others Compression Parameter Index (CPI) used, 0 if unused
*/
- linked_list_t *other_ts;
+ u_int16_t other_cpi;
/**
- * reqid used for this child_sa
+ * List for local traffic selectors
*/
- u_int32_t reqid;
+ linked_list_t *my_ts;
/**
- * encryption algorithm used for this SA
+ * List for remote traffic selectors
*/
- u_int16_t enc_alg;
+ linked_list_t *other_ts;
/**
- * key size of enc_alg
+ * Allocated SPI for a ESP proposal candidates
*/
- u_int16_t enc_size;
+ u_int32_t alloc_esp_spi;
/**
- * integrity protection algorithm used for this SA
+ * Allocated SPI for a AH proposal candidates
*/
- u_int16_t int_alg;
+ u_int32_t alloc_ah_spi;
/**
- * key size of int_alg
+ * Protocol used to protect this SA, ESP|AH
*/
- u_int16_t int_size;
+ protocol_id_t protocol;
/**
- * time, on which SA was installed
+ * reqid used for this child_sa
*/
- time_t install_time;
+ u_int32_t reqid;
/**
- * absolute time when rekeying is sceduled
+ * absolute time when rekeying is scheduled
*/
time_t rekey_time;
/**
+ * absolute time when the SA expires
+ */
+ time_t expire_time;
+
+ /**
* state of the CHILD_SA
*/
child_sa_state_t state;
@@ -166,23 +145,18 @@ struct private_child_sa_t {
ipsec_mode_t mode;
/**
- * virtual IP assinged to local host
- */
- host_t *virtual_ip;
+ * selected proposal
+ */
+ proposal_t *proposal;
/**
* config used to create this child
*/
child_cfg_t *config;
-
- /**
- * cached interface name for iptables
- */
- char *iface;
};
/**
- * Implementation of child_sa_t.get_name.
+ * Implementation of child_sa_t.get_name
*/
static char *get_name(private_child_sa_t *this)
{
@@ -202,11 +176,7 @@ static u_int32_t get_reqid(private_child_sa_t *this)
*/
u_int32_t get_spi(private_child_sa_t *this, bool inbound)
{
- if (inbound)
- {
- return this->me.spi;
- }
- return this->other.spi;
+ return inbound ? this->my_spi : this->other_spi;
}
/**
@@ -214,11 +184,7 @@ u_int32_t get_spi(private_child_sa_t *this, bool inbound)
*/
u_int16_t get_cpi(private_child_sa_t *this, bool inbound)
{
- if (inbound)
- {
- return this->me.cpi;
- }
- return this->other.cpi;
+ return inbound ? this->my_cpi : this->other_cpi;
}
/**
@@ -230,6 +196,30 @@ protocol_id_t get_protocol(private_child_sa_t *this)
}
/**
+ * Implementation of child_sa_t.get_mode
+ */
+static ipsec_mode_t get_mode(private_child_sa_t *this)
+{
+ return this->mode;
+}
+
+/**
+ * Implementation of child_sa_t.has_encap
+ */
+static bool has_encap(private_child_sa_t *this)
+{
+ return this->encap;
+}
+
+/**
+ * Implementation of child_sa_t.get_ipcomp
+ */
+static ipcomp_transform_t get_ipcomp(private_child_sa_t *this)
+{
+ return this->ipcomp;
+}
+
+/**
* Implements child_sa_t.get_state
*/
static child_sa_state_t get_state(private_child_sa_t *this)
@@ -245,207 +235,134 @@ static child_cfg_t* get_config(private_child_sa_t *this)
return this->config;
}
+typedef struct policy_enumerator_t policy_enumerator_t;
+
/**
- * Implementation of child_sa_t.get_stats.
+ * Private policy enumerator
*/
-static void get_stats(private_child_sa_t *this, ipsec_mode_t *mode,
- encryption_algorithm_t *encr_algo, size_t *encr_len,
- integrity_algorithm_t *int_algo, size_t *int_len,
- u_int32_t *rekey, u_int32_t *use_in, u_int32_t *use_out,
- u_int32_t *use_fwd)
+struct policy_enumerator_t {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** enumerator over own TS */
+ enumerator_t *mine;
+ /** enumerator over others TS */
+ enumerator_t *other;
+ /** list of others TS, to recreate enumerator */
+ linked_list_t *list;
+ /** currently enumerating TS for "me" side */
+ traffic_selector_t *ts;
+};
+
+/**
+ * enumerator function of create_policy_enumerator()
+ */
+static bool policy_enumerate(policy_enumerator_t *this,
+ traffic_selector_t **my_out, traffic_selector_t **other_out)
{
- sa_policy_t *policy;
- iterator_t *iterator;
- u_int32_t in = 0, out = 0, fwd = 0, time;
+ traffic_selector_t *other_ts;
- iterator = this->policies->create_iterator(this->policies, TRUE);
- while (iterator->iterate(iterator, (void**)&policy))
+ while (this->ts || this->mine->enumerate(this->mine, &this->ts))
{
-
- if (charon->kernel_interface->query_policy(charon->kernel_interface,
- policy->other_ts, policy->my_ts, POLICY_IN, &time) == SUCCESS)
- {
- in = max(in, time);
+ if (!this->other->enumerate(this->other, &other_ts))
+ { /* end of others list, restart with new of mine */
+ this->other->destroy(this->other);
+ this->other = this->list->create_enumerator(this->list);
+ this->ts = NULL;
+ continue;
}
- if (charon->kernel_interface->query_policy(charon->kernel_interface,
- policy->my_ts, policy->other_ts, POLICY_OUT, &time) == SUCCESS)
- {
- out = max(out, time);
+ if (this->ts->get_type(this->ts) != other_ts->get_type(other_ts))
+ { /* family mismatch */
+ continue;
}
- if (charon->kernel_interface->query_policy(charon->kernel_interface,
- policy->other_ts, policy->my_ts, POLICY_FWD, &time) == SUCCESS)
- {
- fwd = max(fwd, time);
+ if (this->ts->get_protocol(this->ts) &&
+ other_ts->get_protocol(other_ts) &&
+ this->ts->get_protocol(this->ts) != other_ts->get_protocol(other_ts))
+ { /* protocol mismatch */
+ continue;
}
+ *my_out = this->ts;
+ *other_out = other_ts;
+ return TRUE;
}
- iterator->destroy(iterator);
+ return FALSE;
+}
- *mode = this->mode;
- *encr_algo = this->enc_alg;
- *encr_len = this->enc_size;
- *int_algo = this->int_alg;
- *int_len = this->int_size;
- *rekey = this->rekey_time;
- *use_in = in;
- *use_out = out;
- *use_fwd = fwd;
+/**
+ * destroy function of create_policy_enumerator()
+ */
+static void policy_destroy(policy_enumerator_t *this)
+{
+ this->mine->destroy(this->mine);
+ this->other->destroy(this->other);
+ free(this);
}
/**
- * Run the up/down script
+ * Implementation of child_sa_t.create_policy_enumerator
*/
-static void updown(private_child_sa_t *this, bool up)
+static enumerator_t* create_policy_enumerator(private_child_sa_t *this)
{
- sa_policy_t *policy;
- iterator_t *iterator;
- char *script;
-
- script = this->config->get_updown(this->config);
+ policy_enumerator_t *e = malloc_thing(policy_enumerator_t);
- if (script == NULL)
- {
- return;
- }
+ e->public.enumerate = (void*)policy_enumerate;
+ e->public.destroy = (void*)policy_destroy;
+ e->mine = this->my_ts->create_enumerator(this->my_ts);
+ e->other = this->other_ts->create_enumerator(this->other_ts);
+ e->list = this->other_ts;
+ e->ts = NULL;
- iterator = this->policies->create_iterator(this->policies, TRUE);
- while (iterator->iterate(iterator, (void**)&policy))
- {
- char command[1024];
- char *my_client, *other_client, *my_client_mask, *other_client_mask;
- char *pos, *virtual_ip;
- FILE *shell;
-
- /* get subnet/bits from string */
- asprintf(&my_client, "%R", policy->my_ts);
- pos = strchr(my_client, '/');
- *pos = '\0';
- my_client_mask = pos + 1;
- pos = strchr(my_client_mask, '[');
- if (pos)
- {
- *pos = '\0';
- }
- asprintf(&other_client, "%R", policy->other_ts);
- pos = strchr(other_client, '/');
- *pos = '\0';
- other_client_mask = pos + 1;
- pos = strchr(other_client_mask, '[');
- if (pos)
- {
- *pos = '\0';
- }
-
- if (this->virtual_ip)
- {
- asprintf(&virtual_ip, "PLUTO_MY_SOURCEIP='%H' ",
- this->virtual_ip);
- }
- else
- {
- asprintf(&virtual_ip, "");
- }
+ return &e->public;
+}
- /* we cache the iface name, as it may not be available when
- * the SA gets deleted */
- if (up)
- {
- free(this->iface);
- this->iface = charon->kernel_interface->get_interface(
- charon->kernel_interface, this->me.addr);
- }
-
- /* build the command with all env variables.
- * TODO: PLUTO_PEER_CA and PLUTO_NEXT_HOP are currently missing
- */
- snprintf(command, sizeof(command),
- "2>&1 "
- "PLUTO_VERSION='1.1' "
- "PLUTO_VERB='%s%s%s' "
- "PLUTO_CONNECTION='%s' "
- "PLUTO_INTERFACE='%s' "
- "PLUTO_REQID='%u' "
- "PLUTO_ME='%H' "
- "PLUTO_MY_ID='%D' "
- "PLUTO_MY_CLIENT='%s/%s' "
- "PLUTO_MY_CLIENT_NET='%s' "
- "PLUTO_MY_CLIENT_MASK='%s' "
- "PLUTO_MY_PORT='%u' "
- "PLUTO_MY_PROTOCOL='%u' "
- "PLUTO_PEER='%H' "
- "PLUTO_PEER_ID='%D' "
- "PLUTO_PEER_CLIENT='%s/%s' "
- "PLUTO_PEER_CLIENT_NET='%s' "
- "PLUTO_PEER_CLIENT_MASK='%s' "
- "PLUTO_PEER_PORT='%u' "
- "PLUTO_PEER_PROTOCOL='%u' "
- "%s"
- "%s"
- "%s",
- up ? "up" : "down",
- policy->my_ts->is_host(policy->my_ts,
- this->me.addr) ? "-host" : "-client",
- this->me.addr->get_family(this->me.addr) == AF_INET ? "" : "-v6",
- this->config->get_name(this->config),
- this->iface ? this->iface : "unknown",
- this->reqid,
- this->me.addr,
- this->me.id,
- my_client, my_client_mask,
- my_client, my_client_mask,
- policy->my_ts->get_from_port(policy->my_ts),
- policy->my_ts->get_protocol(policy->my_ts),
- this->other.addr,
- this->other.id,
- other_client, other_client_mask,
- other_client, other_client_mask,
- policy->other_ts->get_from_port(policy->other_ts),
- policy->other_ts->get_protocol(policy->other_ts),
- virtual_ip,
- this->config->get_hostaccess(this->config) ?
- "PLUTO_HOST_ACCESS='1' " : "",
- script);
- free(my_client);
- free(other_client);
- free(virtual_ip);
-
- DBG3(DBG_CHD, "running updown script: %s", command);
- shell = popen(command, "r");
+/**
+ * Implementation of child_sa_t.get_usetime
+ */
+static u_int32_t get_usetime(private_child_sa_t *this, bool inbound)
+{
+ enumerator_t *enumerator;
+ traffic_selector_t *my_ts, *other_ts;
+ u_int32_t last_use = 0;
- if (shell == NULL)
- {
- DBG1(DBG_CHD, "could not execute updown script '%s'", script);
- return;
- }
+ enumerator = create_policy_enumerator(this);
+ while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
+ {
+ u_int32_t in, out, fwd;
- while (TRUE)
+ if (inbound)
{
- char resp[128];
-
- if (fgets(resp, sizeof(resp), shell) == NULL)
+ if (charon->kernel_interface->query_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_IN, &in) == SUCCESS)
{
- if (ferror(shell))
- {
- DBG1(DBG_CHD, "error reading output from updown script");
- return;
- }
- else
+ last_use = max(last_use, in);
+ }
+ if (this->mode != MODE_TRANSPORT)
+ {
+ if (charon->kernel_interface->query_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_FWD, &fwd) == SUCCESS)
{
- break;
+ last_use = max(last_use, fwd);
}
}
- else
+ }
+ else
+ {
+ if (charon->kernel_interface->query_policy(charon->kernel_interface,
+ my_ts, other_ts, POLICY_OUT, &out) == SUCCESS)
{
- char *e = resp + strlen(resp);
- if (e > resp && e[-1] == '\n')
- { /* trim trailing '\n' */
- e[-1] = '\0';
- }
- DBG1(DBG_CHD, "updown: %s", resp);
+ last_use = max(last_use, out);
}
}
- pclose(shell);
}
- iterator->destroy(iterator);
+ enumerator->destroy(enumerator);
+ return last_use;
+}
+
+/**
+ * Implementation of child_sa_t.get_lifetime
+ */
+static u_int32_t get_lifetime(private_child_sa_t *this, bool hard)
+{
+ return hard ? this->expire_time : this->rekey_time;
}
/**
@@ -453,11 +370,8 @@ static void updown(private_child_sa_t *this, bool up)
*/
static void set_state(private_child_sa_t *this, child_sa_state_t state)
{
+ charon->bus->child_state_change(charon->bus, &this->public, state);
this->state = state;
- if (state == CHILD_INSTALLED)
- {
- updown(this, TRUE);
- }
}
/**
@@ -474,7 +388,7 @@ static status_t alloc_proposal(private_child_sa_t *this, proposal_t *proposal)
{
if (charon->kernel_interface->get_spi(
charon->kernel_interface,
- this->other.addr, this->me.addr,
+ this->other_addr, this->my_addr,
PROTO_AH, this->reqid,
&this->alloc_ah_spi) != SUCCESS)
{
@@ -490,7 +404,7 @@ static status_t alloc_proposal(private_child_sa_t *this, proposal_t *proposal)
{
if (charon->kernel_interface->get_spi(
charon->kernel_interface,
- this->other.addr, this->me.addr,
+ this->other_addr, this->my_addr,
PROTO_ESP, this->reqid,
&this->alloc_esp_spi) != SUCCESS)
{
@@ -502,7 +416,6 @@ static status_t alloc_proposal(private_child_sa_t *this, proposal_t *proposal)
return SUCCESS;
}
-
/**
* Implements child_sa_t.alloc
*/
@@ -525,237 +438,213 @@ static status_t alloc(private_child_sa_t *this, linked_list_t *proposals)
return SUCCESS;
}
+/**
+ * Install an SA for one direction
+ */
static status_t install(private_child_sa_t *this, proposal_t *proposal,
- ipsec_mode_t mode, prf_plus_t *prf_plus, bool mine)
+ ipsec_mode_t mode, chunk_t integ, chunk_t encr, bool in)
{
- u_int32_t spi, soft, hard;
- host_t *src;
- host_t *dst;
+ u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
+ u_int32_t spi, soft, hard, now;
+ host_t *src, *dst;
status_t status;
- this->protocol = proposal->get_protocol(proposal);
-
- /* now we have to decide which spi to use. Use self allocated, if "mine",
- * or the one in the proposal, if not "mine" (others). Additionally,
+ /* now we have to decide which spi to use. Use self allocated, if "in",
+ * or the one in the proposal, if not "in" (others). Additionally,
* source and dest host switch depending on the role */
- if (mine)
+ if (in)
{
/* if we have allocated SPIs for AH and ESP, we must delete the unused
* one. */
if (this->protocol == PROTO_ESP)
{
- this->me.spi = this->alloc_esp_spi;
+ this->my_spi = this->alloc_esp_spi;
if (this->alloc_ah_spi)
{
- charon->kernel_interface->del_sa(charon->kernel_interface, this->me.addr,
- this->alloc_ah_spi, PROTO_AH);
+ charon->kernel_interface->del_sa(charon->kernel_interface,
+ this->my_addr, this->alloc_ah_spi, 0, PROTO_AH);
}
}
else
{
- this->me.spi = this->alloc_ah_spi;
+ this->my_spi = this->alloc_ah_spi;
if (this->alloc_esp_spi)
{
- charon->kernel_interface->del_sa(charon->kernel_interface, this->me.addr,
- this->alloc_esp_spi, PROTO_ESP);
+ charon->kernel_interface->del_sa(charon->kernel_interface,
+ this->my_addr, this->alloc_esp_spi, 0, PROTO_ESP);
}
}
- spi = this->me.spi;
- dst = this->me.addr;
- src = this->other.addr;
+ spi = this->my_spi;
+ dst = this->my_addr;
+ src = this->other_addr;
}
else
{
- this->other.spi = proposal->get_spi(proposal);
- spi = this->other.spi;
- src = this->me.addr;
- dst = this->other.addr;
+ this->other_spi = proposal->get_spi(proposal);
+ spi = this->other_spi;
+ src = this->my_addr;
+ dst = this->other_addr;
}
- DBG2(DBG_CHD, "adding %s %N SA", mine ? "inbound" : "outbound",
+ DBG2(DBG_CHD, "adding %s %N SA", in ? "inbound" : "outbound",
protocol_id_names, this->protocol);
- /* select encryption algo */
- if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
- &this->enc_alg, &this->enc_size))
- {
- DBG2(DBG_CHD, " using %N for encryption",
- encryption_algorithm_names, this->enc_alg);
- }
-
- /* select integrity algo */
- if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
- &this->int_alg, &this->int_size))
- {
- DBG2(DBG_CHD, " using %N for integrity",
- integrity_algorithm_names, this->int_alg);
- }
- soft = this->config->get_lifetime(this->config, TRUE);
- hard = this->config->get_lifetime(this->config, FALSE);
-
/* send SA down to the kernel */
DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
- if (this->ipcomp != IPCOMP_NONE)
- {
- /* we install an additional IPComp SA */
- u_int32_t cpi = htonl(ntohs(mine ? this->me.cpi : this->other.cpi));
- status = charon->kernel_interface->add_sa(charon->kernel_interface,
- src, dst, cpi, IPPROTO_COMP, this->reqid, 0, 0,
- ENCR_UNDEFINED, 0, AUTH_UNDEFINED, 0, NULL, mode,
- this->ipcomp, FALSE, mine);
- }
+ proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_alg, &size);
+ proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_alg, &size);
+ soft = this->config->get_lifetime(this->config, TRUE);
+ hard = this->config->get_lifetime(this->config, FALSE);
+
status = charon->kernel_interface->add_sa(charon->kernel_interface,
- src, dst, spi, this->protocol, this->reqid, mine ? soft : 0, hard,
- this->enc_alg, this->enc_size, this->int_alg, this->int_size,
- prf_plus, mode, IPCOMP_NONE, this->encap, mine);
-
- this->install_time = time(NULL);
- this->rekey_time = this->install_time + soft;
+ src, dst, spi, this->protocol, this->reqid,
+ in ? soft : 0, hard, enc_alg, encr, int_alg, integ,
+ mode, this->ipcomp, in ? this->my_cpi : this->other_cpi,
+ this->encap, in);
+
+ now = time(NULL);
+ this->rekey_time = now + soft;
+ this->expire_time = now + hard;
return status;
}
-static status_t add(private_child_sa_t *this, proposal_t *proposal,
- ipsec_mode_t mode, prf_plus_t *prf_plus)
+/**
+ * Implementation of child_sa_t.add
+ */
+static status_t add(private_child_sa_t *this,
+ proposal_t *proposal, ipsec_mode_t mode,
+ chunk_t integ_in, chunk_t integ_out,
+ chunk_t encr_in, chunk_t encr_out)
{
- u_int32_t outbound_spi, inbound_spi;
-
- /* backup outbound spi, as alloc overwrites it */
- outbound_spi = proposal->get_spi(proposal);
+ this->proposal = proposal->clone(proposal);
+ this->protocol = proposal->get_protocol(proposal);
- /* get SPIs inbound SAs */
+ /* get SPIs for inbound SAs, write to proposal */
if (alloc_proposal(this, proposal) != SUCCESS)
{
return FAILED;
}
- inbound_spi = proposal->get_spi(proposal);
-
- /* install inbound SAs */
- if (install(this, proposal, mode, prf_plus, TRUE) != SUCCESS)
+ /* install inbound SAs using allocated SPI */
+ if (install(this, proposal, mode, integ_in, encr_in, TRUE) != SUCCESS)
{
return FAILED;
}
-
- /* install outbound SAs, restore spi*/
- proposal->set_spi(proposal, outbound_spi);
- if (install(this, proposal, mode, prf_plus, FALSE) != SUCCESS)
+ /* install outbound SAs using received SPI*/
+ if (install(this, this->proposal, mode, integ_out, encr_out, FALSE) != SUCCESS)
{
return FAILED;
}
- proposal->set_spi(proposal, inbound_spi);
-
return SUCCESS;
}
-static status_t update(private_child_sa_t *this, proposal_t *proposal,
- ipsec_mode_t mode, prf_plus_t *prf_plus)
+/**
+ * Implementation of child_sa_t.update
+ */
+static status_t update(private_child_sa_t *this,
+ proposal_t *proposal, ipsec_mode_t mode,
+ chunk_t integ_in, chunk_t integ_out,
+ chunk_t encr_in, chunk_t encr_out)
{
- u_int32_t inbound_spi;
-
- /* backup received spi, as install() overwrites it */
- inbound_spi = proposal->get_spi(proposal);
+ this->proposal = proposal->clone(proposal);
+ this->protocol = proposal->get_protocol(proposal);
/* install outbound SAs */
- if (install(this, proposal, mode, prf_plus, FALSE) != SUCCESS)
+ if (install(this, proposal, mode, integ_out, encr_out, FALSE) != SUCCESS)
{
return FAILED;
}
-
- /* restore spi */
- proposal->set_spi(proposal, inbound_spi);
/* install inbound SAs */
- if (install(this, proposal, mode, prf_plus, TRUE) != SUCCESS)
+ if (install(this, proposal, mode, integ_in, encr_in, TRUE) != SUCCESS)
{
return FAILED;
}
-
return SUCCESS;
}
+/**
+ * Implementation of child_sa_t.get_proposal
+ */
+static proposal_t* get_proposal(private_child_sa_t *this)
+{
+ return this->proposal;
+}
+
+/**
+ * Implementation of child_sa_t.add_policies
+ */
static status_t add_policies(private_child_sa_t *this,
linked_list_t *my_ts_list, linked_list_t *other_ts_list,
ipsec_mode_t mode, protocol_id_t proto)
{
- iterator_t *my_iter, *other_iter;
+ enumerator_t *enumerator;
traffic_selector_t *my_ts, *other_ts;
- /* use low prio for ROUTED policies */
- bool high_prio = (this->state != CHILD_CREATED);
+ status_t status = SUCCESS;
+ bool routed = (this->state == CHILD_CREATED);
if (this->protocol == PROTO_NONE)
{ /* update if not set yet */
this->protocol = proto;
}
+
+ /* apply traffic selectors */
+ enumerator = my_ts_list->create_enumerator(my_ts_list);
+ while (enumerator->enumerate(enumerator, &my_ts))
+ {
+ this->my_ts->insert_last(this->my_ts, my_ts->clone(my_ts));
+ }
+ enumerator->destroy(enumerator);
+ enumerator = other_ts_list->create_enumerator(other_ts_list);
+ while (enumerator->enumerate(enumerator, &other_ts))
+ {
+ this->other_ts->insert_last(this->other_ts, other_ts->clone(other_ts));
+ }
+ enumerator->destroy(enumerator);
- /* iterate over both lists */
- my_iter = my_ts_list->create_iterator(my_ts_list, TRUE);
- other_iter = other_ts_list->create_iterator(other_ts_list, TRUE);
- while (my_iter->iterate(my_iter, (void**)&my_ts))
+ if (this->config->install_policy(this->config))
{
- other_iter->reset(other_iter);
- while (other_iter->iterate(other_iter, (void**)&other_ts))
+ /* enumerate pairs of traffic selectors */
+ enumerator = create_policy_enumerator(this);
+ while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
- /* set up policies for every entry in my_ts_list to every entry in other_ts_list */
- status_t status;
- sa_policy_t *policy;
-
- if (my_ts->get_type(my_ts) != other_ts->get_type(other_ts))
- {
- DBG2(DBG_CHD,
- "CHILD_SA policy uses two different IP families - ignored");
- continue;
- }
-
- /* only set up policies if protocol matches, or if one is zero (any) */
- if (my_ts->get_protocol(my_ts) != other_ts->get_protocol(other_ts) &&
- my_ts->get_protocol(my_ts) && other_ts->get_protocol(other_ts))
- {
- DBG2(DBG_CHD,
- "CHILD_SA policy uses two different protocols - ignored");
- continue;
- }
-
/* install 3 policies: out, in and forward */
- status = charon->kernel_interface->add_policy(charon->kernel_interface,
- this->me.addr, this->other.addr, my_ts, other_ts, POLICY_OUT,
- this->protocol, this->reqid, high_prio, mode, this->ipcomp);
-
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
- this->other.addr, this->me.addr, other_ts, my_ts, POLICY_IN,
- this->protocol, this->reqid, high_prio, mode, this->ipcomp);
+ this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT,
+ this->other_spi, this->protocol, this->reqid, mode, this->ipcomp,
+ this->other_cpi, routed);
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
- this->other.addr, this->me.addr, other_ts, my_ts, POLICY_FWD,
- this->protocol, this->reqid, high_prio, mode, this->ipcomp);
+ this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN,
+ this->my_spi, this->protocol, this->reqid, mode, this->ipcomp,
+ this->my_cpi, routed);
+ if (mode != MODE_TRANSPORT)
+ {
+ status |= charon->kernel_interface->add_policy(charon->kernel_interface,
+ this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD,
+ this->my_spi, this->protocol, this->reqid, mode, this->ipcomp,
+ this->my_cpi, routed);
+ }
if (status != SUCCESS)
{
- my_iter->destroy(my_iter);
- other_iter->destroy(other_iter);
- return status;
+ break;
}
-
- /* store policy to delete/update them later */
- policy = malloc_thing(sa_policy_t);
- policy->my_ts = my_ts->clone(my_ts);
- policy->other_ts = other_ts->clone(other_ts);
- this->policies->insert_last(this->policies, policy);
- /* add to separate list to query them via get_*_traffic_selectors() */
- this->my_ts->insert_last(this->my_ts, policy->my_ts);
- this->other_ts->insert_last(this->other_ts, policy->other_ts);
}
+ enumerator->destroy(enumerator);
}
- my_iter->destroy(my_iter);
- other_iter->destroy(other_iter);
- /* switch to routed state if no SAD entry set up */
- if (this->state == CHILD_CREATED)
+ if (status == SUCCESS)
{
- this->state = CHILD_ROUTED;
+ /* switch to routed state if no SAD entry set up */
+ if (this->state == CHILD_CREATED)
+ {
+ set_state(this, CHILD_ROUTED);
+ }
+ /* needed to update hosts */
+ this->mode = mode;
}
- /* needed to update hosts */
- this->mode = mode;
- return SUCCESS;
+ return status;
}
/**
@@ -763,166 +652,143 @@ static status_t add_policies(private_child_sa_t *this,
*/
static linked_list_t *get_traffic_selectors(private_child_sa_t *this, bool local)
{
- if (local)
- {
- return this->my_ts;
- }
- return this->other_ts;
-}
-
-/**
- * Implementation of child_sa_t.get_use_time
- */
-static status_t get_use_time(private_child_sa_t *this, bool inbound, time_t *use_time)
-{
- iterator_t *iterator;
- sa_policy_t *policy;
- status_t status = FAILED;
-
- *use_time = UNDEFINED_TIME;
-
- iterator = this->policies->create_iterator(this->policies, TRUE);
- while (iterator->iterate(iterator, (void**)&policy))
- {
- if (inbound)
- {
- time_t in = UNDEFINED_TIME, fwd = UNDEFINED_TIME;
-
- status = charon->kernel_interface->query_policy(
- charon->kernel_interface,
- policy->other_ts, policy->my_ts,
- POLICY_IN, (u_int32_t*)&in);
- status |= charon->kernel_interface->query_policy(
- charon->kernel_interface,
- policy->other_ts, policy->my_ts,
- POLICY_FWD, (u_int32_t*)&fwd);
- *use_time = max(in, fwd);
- }
- else
- {
- status = charon->kernel_interface->query_policy(
- charon->kernel_interface,
- policy->my_ts, policy->other_ts,
- POLICY_OUT, (u_int32_t*)use_time);
- }
- }
- iterator->destroy(iterator);
- return status;
+ return local ? this->my_ts : this->other_ts;
}
/**
* Implementation of child_sa_t.update_hosts.
*/
static status_t update_hosts(private_child_sa_t *this,
- host_t *me, host_t *other, bool encap)
+ host_t *me, host_t *other, host_t *vip, bool encap)
{
+ child_sa_state_t old;
+ bool transport_proxy_mode;
+
/* anything changed at all? */
- if (me->equals(me, this->me.addr) &&
- other->equals(other, this->other.addr) && this->encap == encap)
+ if (me->equals(me, this->my_addr) &&
+ other->equals(other, this->other_addr) && this->encap == encap)
{
return SUCCESS;
}
- /* run updown script to remove iptables rules */
- updown(this, FALSE);
-
- this->encap = encap;
-
- if (this->ipcomp != IPCOMP_NONE)
- {
- /* update our (initator) IPComp SA */
- charon->kernel_interface->update_sa(charon->kernel_interface, htonl(ntohs(this->me.cpi)),
- IPPROTO_COMP, this->other.addr, this->me.addr, other, me, FALSE);
- /* update his (responder) IPComp SA */
- charon->kernel_interface->update_sa(charon->kernel_interface, htonl(ntohs(this->other.cpi)),
- IPPROTO_COMP, this->me.addr, this->other.addr, me, other, FALSE);
- }
- /* update our (initator) SA */
- charon->kernel_interface->update_sa(charon->kernel_interface, this->me.spi,
- this->protocol, this->other.addr, this->me.addr, other, me, encap);
- /* update his (responder) SA */
- charon->kernel_interface->update_sa(charon->kernel_interface, this->other.spi,
- this->protocol, this->me.addr, this->other.addr, me, other, encap);
+ old = this->state;
+ set_state(this, CHILD_UPDATING);
+ transport_proxy_mode = this->config->use_proxy_mode(this->config) &&
+ this->mode == MODE_TRANSPORT;
- /* update policies */
- if (!me->ip_equals(me, this->me.addr) ||
- !other->ip_equals(other, this->other.addr))
+ if (!transport_proxy_mode)
{
- iterator_t *iterator;
- sa_policy_t *policy;
-
- /* always use high priorities, as hosts getting updated are INSTALLED */
- iterator = this->policies->create_iterator(this->policies, TRUE);
- while (iterator->iterate(iterator, (void**)&policy))
+ /* update our (initator) SA */
+ if (this->my_spi)
{
- /* remove old policies first */
- charon->kernel_interface->del_policy(charon->kernel_interface,
- policy->my_ts, policy->other_ts, POLICY_OUT);
- charon->kernel_interface->del_policy(charon->kernel_interface,
- policy->other_ts, policy->my_ts, POLICY_IN);
- charon->kernel_interface->del_policy(charon->kernel_interface,
- policy->other_ts, policy->my_ts, POLICY_FWD);
-
- /* check wether we have to update a "dynamic" traffic selector */
- if (!me->ip_equals(me, this->me.addr) &&
- policy->my_ts->is_host(policy->my_ts, this->me.addr))
+ if (charon->kernel_interface->update_sa(charon->kernel_interface,
+ this->my_spi, this->protocol,
+ this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
+ this->other_addr, this->my_addr, other, me,
+ this->encap, encap) == NOT_SUPPORTED)
{
- policy->my_ts->set_address(policy->my_ts, me);
+ return NOT_SUPPORTED;
}
- if (!other->ip_equals(other, this->other.addr) &&
- policy->other_ts->is_host(policy->other_ts, this->other.addr))
+ }
+
+ /* update his (responder) SA */
+ if (this->other_spi)
+ {
+ if (charon->kernel_interface->update_sa(charon->kernel_interface,
+ this->other_spi, this->protocol,
+ this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
+ this->my_addr, this->other_addr, me, other,
+ this->encap, encap) == NOT_SUPPORTED)
{
- policy->other_ts->set_address(policy->other_ts, other);
+ return NOT_SUPPORTED;
}
+ }
+ }
+
+ if (this->config->install_policy(this->config))
+ {
+ /* update policies */
+ if (!me->ip_equals(me, this->my_addr) ||
+ !other->ip_equals(other, this->other_addr))
+ {
+ enumerator_t *enumerator;
+ traffic_selector_t *my_ts, *other_ts;
- /* we reinstall the virtual IP to handle interface romaing
- * correctly */
- if (this->virtual_ip)
+ /* always use high priorities, as hosts getting updated are INSTALLED */
+ enumerator = create_policy_enumerator(this);
+ while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
- charon->kernel_interface->del_ip(charon->kernel_interface,
- this->virtual_ip);
- charon->kernel_interface->add_ip(charon->kernel_interface,
- this->virtual_ip, me);
+ /* remove old policies first */
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ my_ts, other_ts, POLICY_OUT, FALSE);
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_IN, FALSE);
+ if (this->mode != MODE_TRANSPORT)
+ {
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_FWD, FALSE);
+ }
+
+ /* check whether we have to update a "dynamic" traffic selector */
+ if (!me->ip_equals(me, this->my_addr) &&
+ my_ts->is_host(my_ts, this->my_addr))
+ {
+ my_ts->set_address(my_ts, me);
+ }
+ if (!other->ip_equals(other, this->other_addr) &&
+ other_ts->is_host(other_ts, this->other_addr))
+ {
+ other_ts->set_address(other_ts, other);
+ }
+
+ /* we reinstall the virtual IP to handle interface roaming
+ * correctly */
+ if (vip)
+ {
+ charon->kernel_interface->del_ip(charon->kernel_interface, vip);
+ charon->kernel_interface->add_ip(charon->kernel_interface, vip, me);
+ }
+
+ /* reinstall updated policies */
+ charon->kernel_interface->add_policy(charon->kernel_interface,
+ me, other, my_ts, other_ts, POLICY_OUT, this->other_spi,
+ this->protocol, this->reqid, this->mode, this->ipcomp,
+ this->other_cpi, FALSE);
+ charon->kernel_interface->add_policy(charon->kernel_interface,
+ other, me, other_ts, my_ts, POLICY_IN, this->my_spi,
+ this->protocol, this->reqid, this->mode, this->ipcomp,
+ this->my_cpi, FALSE);
+ if (this->mode != MODE_TRANSPORT)
+ {
+ charon->kernel_interface->add_policy(charon->kernel_interface,
+ other, me, other_ts, my_ts, POLICY_FWD, this->my_spi,
+ this->protocol, this->reqid, this->mode, this->ipcomp,
+ this->my_cpi, FALSE);
+ }
}
-
- /* reinstall updated policies */
- charon->kernel_interface->add_policy(charon->kernel_interface,
- me, other, policy->my_ts, policy->other_ts, POLICY_OUT,
- this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
- charon->kernel_interface->add_policy(charon->kernel_interface,
- other, me, policy->other_ts, policy->my_ts, POLICY_IN,
- this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
- charon->kernel_interface->add_policy(charon->kernel_interface,
- other, me, policy->other_ts, policy->my_ts, POLICY_FWD,
- this->protocol, this->reqid, TRUE, this->mode, this->ipcomp);
+ enumerator->destroy(enumerator);
}
- iterator->destroy(iterator);
}
- /* apply hosts */
- if (!me->equals(me, this->me.addr))
+ if (!transport_proxy_mode)
{
- this->me.addr->destroy(this->me.addr);
- this->me.addr = me->clone(me);
- }
- if (!other->equals(other, this->other.addr))
- {
- this->other.addr->destroy(this->other.addr);
- this->other.addr = other->clone(other);
+ /* apply hosts */
+ if (!me->equals(me, this->my_addr))
+ {
+ this->my_addr->destroy(this->my_addr);
+ this->my_addr = me->clone(me);
+ }
+ if (!other->equals(other, this->other_addr))
+ {
+ this->other_addr->destroy(this->other_addr);
+ this->other_addr = other->clone(other);
+ }
}
-
- /* install new iptables rules */
- updown(this, TRUE);
-
- return SUCCESS;
-}
-/**
- * Implementation of child_sa_t.set_virtual_ip.
- */
-static void set_virtual_ip(private_child_sa_t *this, host_t *ip)
-{
- this->virtual_ip = ip->clone(ip);
+ this->encap = encap;
+ set_state(this, old);
+
+ return SUCCESS;
}
/**
@@ -932,7 +798,7 @@ static void activate_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp,
u_int16_t other_cpi)
{
this->ipcomp = ipcomp;
- this->other.cpi = other_cpi;
+ this->other_cpi = other_cpi;
}
/**
@@ -943,10 +809,10 @@ static u_int16_t allocate_cpi(private_child_sa_t *this)
if (!this->cpi_allocated)
{
charon->kernel_interface->get_cpi(charon->kernel_interface,
- this->other.addr, this->me.addr, this->reqid, &this->me.cpi);
+ this->other_addr, this->my_addr, this->reqid, &this->my_cpi);
this->cpi_allocated = TRUE;
}
- return this->me.cpi;
+ return this->my_cpi;
}
/**
@@ -954,75 +820,61 @@ static u_int16_t allocate_cpi(private_child_sa_t *this)
*/
static void destroy(private_child_sa_t *this)
{
- sa_policy_t *policy;
+ enumerator_t *enumerator;
+ traffic_selector_t *my_ts, *other_ts;
+ bool unrouted = (this->state == CHILD_ROUTED);
- if (this->state == CHILD_DELETING || this->state == CHILD_INSTALLED)
- {
- updown(this, FALSE);
- }
+ set_state(this, CHILD_DESTROYING);
/* delete SAs in the kernel, if they are set up */
- if (this->me.spi)
- {
- charon->kernel_interface->del_sa(charon->kernel_interface,
- this->me.addr, this->me.spi, this->protocol);
- }
- if (this->alloc_esp_spi && this->alloc_esp_spi != this->me.spi)
+ if (this->my_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->me.addr, this->alloc_esp_spi, PROTO_ESP);
+ this->my_addr, this->my_spi, this->protocol,
+ this->my_cpi);
}
- if (this->alloc_ah_spi && this->alloc_ah_spi != this->me.spi)
+ if (this->alloc_esp_spi && this->alloc_esp_spi != this->my_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->me.addr, this->alloc_ah_spi, PROTO_AH);
+ this->my_addr, this->alloc_esp_spi, PROTO_ESP, 0);
}
- if (this->other.spi)
+ if (this->alloc_ah_spi && this->alloc_ah_spi != this->my_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->other.addr, this->other.spi, this->protocol);
+ this->my_addr, this->alloc_ah_spi, PROTO_AH, 0);
}
- if (this->me.cpi)
+ if (this->other_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
- this->me.addr, htonl(ntohs(this->me.cpi)), IPPROTO_COMP);
- }
- if (this->other.cpi)
- {
- charon->kernel_interface->del_sa(charon->kernel_interface,
- this->other.addr, htonl(ntohs(this->other.cpi)), IPPROTO_COMP);
+ this->other_addr, this->other_spi, this->protocol,
+ this->other_cpi);
}
- /* delete all policies in the kernel */
- while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS)
+ if (this->config->install_policy(this->config))
{
- /* let rekeyed policies, as they are used by another child_sa */
- charon->kernel_interface->del_policy(charon->kernel_interface,
- policy->my_ts, policy->other_ts,
- POLICY_OUT);
-
- charon->kernel_interface->del_policy(charon->kernel_interface,
- policy->other_ts, policy->my_ts,
- POLICY_IN);
-
- charon->kernel_interface->del_policy(charon->kernel_interface,
- policy->other_ts, policy->my_ts,
- POLICY_FWD);
- policy->my_ts->destroy(policy->my_ts);
- policy->other_ts->destroy(policy->other_ts);
- free(policy);
+ /* delete all policies in the kernel */
+ enumerator = create_policy_enumerator(this);
+ while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
+ {
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ my_ts, other_ts, POLICY_OUT, unrouted);
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_IN, unrouted);
+ if (this->mode != MODE_TRANSPORT)
+ {
+ charon->kernel_interface->del_policy(charon->kernel_interface,
+ other_ts, my_ts, POLICY_FWD, unrouted);
+ }
+ }
+ enumerator->destroy(enumerator);
}
- this->policies->destroy(this->policies);
- this->my_ts->destroy(this->my_ts);
- this->other_ts->destroy(this->other_ts);
- this->me.addr->destroy(this->me.addr);
- this->other.addr->destroy(this->other.addr);
- this->me.id->destroy(this->me.id);
- this->other.id->destroy(this->other.id);
+ this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
+ this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
+ this->my_addr->destroy(this->my_addr);
+ this->other_addr->destroy(this->other_addr);
+ DESTROY_IF(this->proposal);
this->config->destroy(this->config);
- free(this->iface);
- DESTROY_IF(this->virtual_ip);
free(this);
}
@@ -1030,7 +882,6 @@ static void destroy(private_child_sa_t *this)
* Described in header.
*/
child_sa_t * child_sa_create(host_t *me, host_t* other,
- identification_t *my_id, identification_t *other_id,
child_cfg_t *config, u_int32_t rekey, bool encap)
{
static u_int32_t reqid = 0;
@@ -1042,31 +893,33 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->public.get_spi = (u_int32_t(*)(child_sa_t*, bool))get_spi;
this->public.get_cpi = (u_int16_t(*)(child_sa_t*, bool))get_cpi;
this->public.get_protocol = (protocol_id_t(*)(child_sa_t*))get_protocol;
- this->public.get_stats = (void(*)(child_sa_t*, ipsec_mode_t*,encryption_algorithm_t*,size_t*,integrity_algorithm_t*,size_t*,u_int32_t*,u_int32_t*,u_int32_t*,u_int32_t*))get_stats;
+ this->public.get_mode = (ipsec_mode_t(*)(child_sa_t*))get_mode;
+ this->public.get_ipcomp = (ipcomp_transform_t(*)(child_sa_t*))get_ipcomp;
+ this->public.has_encap = (bool(*)(child_sa_t*))has_encap;
+ this->public.get_lifetime = (u_int32_t(*)(child_sa_t*, bool))get_lifetime;
+ this->public.get_usetime = (u_int32_t(*)(child_sa_t*, bool))get_usetime;
this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc;
- this->public.add = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,prf_plus_t*))add;
- this->public.update = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,prf_plus_t*))update;
- this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,bool))update_hosts;
+ this->public.add = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,chunk_t,chunk_t,chunk_t,chunk_t))add;
+ this->public.update = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,chunk_t,chunk_t,chunk_t,chunk_t))update;
+ this->public.get_proposal = (proposal_t*(*)(child_sa_t*))get_proposal;
+ this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,host_t*,bool))update_hosts;
this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*,ipsec_mode_t,protocol_id_t))add_policies;
this->public.get_traffic_selectors = (linked_list_t*(*)(child_sa_t*,bool))get_traffic_selectors;
- this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time;
+ this->public.create_policy_enumerator = (enumerator_t*(*)(child_sa_t*))create_policy_enumerator;
this->public.set_state = (void(*)(child_sa_t*,child_sa_state_t))set_state;
this->public.get_state = (child_sa_state_t(*)(child_sa_t*))get_state;
this->public.get_config = (child_cfg_t*(*)(child_sa_t*))get_config;
this->public.activate_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t,u_int16_t))activate_ipcomp;
this->public.allocate_cpi = (u_int16_t(*)(child_sa_t*))allocate_cpi;
- this->public.set_virtual_ip = (void(*)(child_sa_t*,host_t*))set_virtual_ip;
this->public.destroy = (void(*)(child_sa_t*))destroy;
/* private data */
- this->me.addr = me->clone(me);
- this->other.addr = other->clone(other);
- this->me.id = my_id->clone(my_id);
- this->other.id = other_id->clone(other_id);
- this->me.spi = 0;
- this->me.cpi = 0;
- this->other.spi = 0;
- this->other.cpi = 0;
+ this->my_addr = me->clone(me);
+ this->other_addr = other->clone(other);
+ this->my_spi = 0;
+ this->my_cpi = 0;
+ this->other_spi = 0;
+ this->other_cpi = 0;
this->alloc_ah_spi = 0;
this->alloc_esp_spi = 0;
this->encap = encap;
@@ -1075,19 +928,70 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->state = CHILD_CREATED;
/* reuse old reqid if we are rekeying an existing CHILD_SA */
this->reqid = rekey ? rekey : ++reqid;
- this->enc_alg = ENCR_UNDEFINED;
- this->enc_size = 0;
- this->int_alg = AUTH_UNDEFINED;
- this->int_size = 0;
- this->policies = linked_list_create();
this->my_ts = linked_list_create();
this->other_ts = linked_list_create();
this->protocol = PROTO_NONE;
this->mode = MODE_TUNNEL;
- this->virtual_ip = NULL;
- this->iface = NULL;
+ this->proposal = NULL;
this->config = config;
config->get_ref(config);
+
+ /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
+ if (config->get_mode(config) == MODE_TRANSPORT &&
+ config->use_proxy_mode(config))
+ {
+ ts_type_t type;
+ int family;
+ chunk_t addr;
+ host_t *host;
+ enumerator_t *enumerator;
+ linked_list_t *my_ts_list, *other_ts_list;
+ traffic_selector_t *my_ts, *other_ts;
+
+ this->mode = MODE_TRANSPORT;
+
+ my_ts_list = config->get_traffic_selectors(config, TRUE, NULL, me);
+ enumerator = my_ts_list->create_enumerator(my_ts_list);
+ if (enumerator->enumerate(enumerator, &my_ts))
+ {
+ if (my_ts->is_host(my_ts, NULL) &&
+ !my_ts->is_host(my_ts, this->my_addr))
+ {
+ type = my_ts->get_type(my_ts);
+ family = (type == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6;
+ addr = my_ts->get_from_address(my_ts);
+ host = host_create_from_chunk(family, addr, 0);
+ free(addr.ptr);
+ DBG1(DBG_CHD, "my address: %H is a transport mode proxy for %H",
+ this->my_addr, host);
+ this->my_addr->destroy(this->my_addr);
+ this->my_addr = host;
+ }
+ }
+ enumerator->destroy(enumerator);
+ my_ts_list->destroy_offset(my_ts_list, offsetof(traffic_selector_t, destroy));
+
+ other_ts_list = config->get_traffic_selectors(config, FALSE, NULL, other);
+ enumerator = other_ts_list->create_enumerator(other_ts_list);
+ if (enumerator->enumerate(enumerator, &other_ts))
+ {
+ if (other_ts->is_host(other_ts, NULL) &&
+ !other_ts->is_host(other_ts, this->other_addr))
+ {
+ type = other_ts->get_type(other_ts);
+ family = (type == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6;
+ addr = other_ts->get_from_address(other_ts);
+ host = host_create_from_chunk(family, addr, 0);
+ free(addr.ptr);
+ DBG1(DBG_CHD, "other address: %H is a transport mode proxy for %H",
+ this->other_addr, host);
+ this->other_addr->destroy(this->other_addr);
+ this->other_addr = host;
+ }
+ }
+ enumerator->destroy(enumerator);
+ other_ts_list->destroy_offset(other_ts_list, offsetof(traffic_selector_t, destroy));
+ }
return &this->public;
}
diff --git a/src/charon/sa/child_sa.h b/src/charon/sa/child_sa.h
index 2f7961e03..7109de5cd 100644
--- a/src/charon/sa/child_sa.h
+++ b/src/charon/sa/child_sa.h
@@ -14,7 +14,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: child_sa.h 4358 2008-09-25 13:56:23Z tobias $
+ * $Id: child_sa.h 4618 2008-11-11 09:22:00Z tobias $
*/
/**
@@ -50,11 +50,21 @@ enum child_sa_state_t {
CHILD_ROUTED,
/**
+ * Installing an in-use CHILD_SA
+ */
+ CHILD_INSTALLING,
+
+ /**
* Installed an in-use CHILD_SA
*/
CHILD_INSTALLED,
/**
+ * While updating hosts, in update_hosts()
+ */
+ CHILD_UPDATING,
+
+ /**
* CHILD_SA which is rekeying
*/
CHILD_REKEYING,
@@ -63,6 +73,11 @@ enum child_sa_state_t {
* CHILD_SA in progress of delete
*/
CHILD_DELETING,
+
+ /**
+ * CHILD_SA object gets destroyed
+ */
+ CHILD_DESTROYING,
};
/**
@@ -138,23 +153,41 @@ struct child_sa_t {
protocol_id_t (*get_protocol) (child_sa_t *this);
/**
- * Get info and statistics about this CHILD_SA.
+ * Get the IPsec mode of this CHILD_SA.
+ *
+ * @return TUNNEL | TRANSPORT | BEET
+ */
+ ipsec_mode_t (*get_mode)(child_sa_t *this);
+
+ /**
+ * Get the used IPComp algorithm.
+ *
+ * @return IPComp compression algorithm.
+ */
+ ipcomp_transform_t (*get_ipcomp)(child_sa_t *this);
+
+ /**
+ * Check if this CHILD_SA uses UDP encapsulation.
+ *
+ * @return TRUE if SA encapsulates ESP packets
+ */
+ bool (*has_encap)(child_sa_t *this);
+
+ /**
+ * Get the lifetime of the CHILD_SA.
*
- * @param mode mode this IKE_SA uses
- * @param encr_algo encryption algorithm used by this CHILD_SA.
- * @param encr_len key length of the algorithm, if any
- * @param int_algo integrity algorithm used by this CHILD_SA
- * @param int_len key length of the algorithm, if any
- * @param rekey time when rekeying is scheduled
- * @param use_in time when last traffic was seen coming in
- * @param use_out time when last traffic was seen going out
- * @param use_fwd time when last traffic was getting forwarded
+ * @param hard TRUE for hard lifetime, FALSE for soft (rekey) lifetime
+ * @return lifetime in seconds
*/
- void (*get_stats)(child_sa_t *this, ipsec_mode_t *mode,
- encryption_algorithm_t *encr, size_t *encr_len,
- integrity_algorithm_t *int_algo, size_t *int_len,
- u_int32_t *rekey, u_int32_t *use_in, u_int32_t *use_out,
- u_int32_t *use_fwd);
+ u_int32_t (*get_lifetime)(child_sa_t *this, bool hard);
+
+ /**
+ * Get last use time of the CHILD_SA.
+ *
+ * @param inbound TRUE for inbound traffic, FALSE for outbound
+ * @return time of last use in seconds
+ */
+ u_int32_t (*get_usetime)(child_sa_t *this, bool inbound);
/**
* Allocate SPIs for given proposals.
@@ -174,12 +207,15 @@ struct child_sa_t {
*
* @param proposal proposal for which SPIs are allocated
* @param mode mode for the CHILD_SA
- * @param prf_plus key material to use for key derivation
+ * @param integ_in integrity key for inbound traffic
+ * @param integ_out integrity key for outbound traffic
+ * @param encr_in encryption key for inbound traffic
+ * @param enc_out encryption key for outbound traffic
* @return SUCCESS or FAILED
*/
status_t (*add)(child_sa_t *this, proposal_t *proposal, ipsec_mode_t mode,
- prf_plus_t *prf_plus);
-
+ chunk_t integ_in, chunk_t integ_out,
+ chunk_t encr_in, chunk_t encr_out);
/**
* Install the kernel SAs for a proposal, after SPIs have been allocated.
*
@@ -187,12 +223,22 @@ struct child_sa_t {
*
* @param proposal proposal for which SPIs are allocated
* @param mode mode for the CHILD_SA
- * @param prf_plus key material to use for key derivation
+ * @param integ_in integrity key for inbound traffic
+ * @param integ_out integrity key for outbound traffic
+ * @param encr_in encryption key for inbound traffic
+ * @param enc_out encryption key for outbound traffic
* @return SUCCESS or FAILED
*/
status_t (*update)(child_sa_t *this, proposal_t *proposal, ipsec_mode_t mode,
- prf_plus_t *prf_plus);
-
+ chunk_t integ_in, chunk_t integ_out,
+ chunk_t encr_in, chunk_t encr_out);
+ /**
+ * Get the selected proposal passed to add()/update().
+ *
+ * @return selected proposal
+ */
+ proposal_t* (*get_proposal)(child_sa_t *this);
+
/**
* Update the hosts in the kernel SAs and policies.
*
@@ -200,11 +246,12 @@ struct child_sa_t {
*
* @param me the new local host
* @param other the new remote host
+ * @param vip virtual IP, if any
* @param TRUE to use UDP encapsulation for NAT traversal
* @return SUCCESS or FAILED
*/
status_t (*update_hosts)(child_sa_t *this, host_t *me, host_t *other,
- bool encap);
+ host_t *vip, bool encap);
/**
* Install the policies using some traffic selectors.
@@ -231,13 +278,11 @@ struct child_sa_t {
linked_list_t* (*get_traffic_selectors) (child_sa_t *this, bool local);
/**
- * Get the time of this child_sa_t's last use (i.e. last use of any of its policies)
- *
- * @param inbound query for in- or outbound usage
- * @param use_time the time
- * @return SUCCESS or FAILED
- */
- status_t (*get_use_time) (child_sa_t *this, bool inbound, time_t *use_time);
+ * Create an enumerator over installed policies.
+ *
+ * @return enumerator over pairs of traffic selectors.
+ */
+ enumerator_t* (*create_policy_enumerator)(child_sa_t *this);
/**
* Get the state of the CHILD_SA.
@@ -259,23 +304,13 @@ struct child_sa_t {
child_cfg_t* (*get_config) (child_sa_t *this);
/**
- * Set the virtual IP used received from IRAS.
- *
- * To allow proper setup of firewall rules, the virtual IP is required
- * for filtering.
- *
- * @param ip own virtual IP
- */
- void (*set_virtual_ip) (child_sa_t *this, host_t *ip);
-
- /**
* Activate IPComp by setting the transform ID and CPI values.
*
* @param ipcomp the IPComp transform to use
* @param other_cpi other Compression Parameter Index
*/
void (*activate_ipcomp) (child_sa_t *this, ipcomp_transform_t ipcomp,
- u_int16_t other_cpi);
+ u_int16_t other_cpi);
/**
* Returns the Compression Parameter Index (CPI) allocated from the kernel.
@@ -293,17 +328,16 @@ struct child_sa_t {
/**
* Constructor to create a new child_sa_t.
*
- * @param me own address
- * @param other remote address
- * @param my_id id of own peer
- * @param other_id id of remote peer
- * @param config config to use for this CHILD_SA
- * @param reqid reqid of old CHILD_SA when rekeying, 0 otherwise
- * @param encap TRUE to enable UDP encapsulation (NAT traversal)
- * @return child_sa_t object
+ * @param me own address
+ * @param other remote address
+ * @param my_id id of own peer
+ * @param other_id id of remote peer
+ * @param config config to use for this CHILD_SA
+ * @param reqid reqid of old CHILD_SA when rekeying, 0 otherwise
+ * @param encap TRUE to enable UDP encapsulation (NAT traversal)
+ * @return child_sa_t object
*/
-child_sa_t * child_sa_create(host_t *me, host_t *other,
- identification_t *my_id, identification_t* other_id,
- child_cfg_t *config, u_int32_t reqid, bool encap);
+child_sa_t * child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
+ u_int32_t reqid, bool encap);
#endif /*CHILD_SA_H_ @} */
diff --git a/src/charon/sa/connect_manager.c b/src/charon/sa/connect_manager.c
index d24ce8fc7..b9141ffc1 100644
--- a/src/charon/sa/connect_manager.c
+++ b/src/charon/sa/connect_manager.c
@@ -12,15 +12,15 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: connect_manager.c 4192 2008-07-18 15:51:40Z martin $
+ * $Id: connect_manager.c 4579 2008-11-05 11:29:56Z martin $
*/
#include "connect_manager.h"
-#include <pthread.h>
#include <math.h>
#include <daemon.h>
+#include <utils/mutex.h>
#include <utils/linked_list.h>
#include <crypto/hashers/hasher.h>
@@ -59,7 +59,7 @@ struct private_connect_manager_t {
/**
* Lock for exclusivly accessing the manager.
*/
- pthread_mutex_t mutex;
+ mutex_t *mutex;
/**
* Hasher to generate signatures
@@ -845,20 +845,20 @@ static job_requeue_t initiator_finish(callback_data_t *data)
{
private_connect_manager_t *this = data->connect_manager;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
check_list_t *checklist;
if (get_checklist_by_id(this, data->connect_id, &checklist) != SUCCESS)
{
DBG1(DBG_IKE, "checklist with id '%#B' not found, can't finish connectivity checks",
&data->connect_id);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return JOB_REQUEUE_NONE;
}
finish_checks(this, checklist);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return JOB_REQUEUE_NONE;
}
@@ -929,14 +929,14 @@ static job_requeue_t retransmit(callback_data_t *data)
{
private_connect_manager_t *this = data->connect_manager;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
check_list_t *checklist;
if (get_checklist_by_id(this, data->connect_id, &checklist) != SUCCESS)
{
DBG1(DBG_IKE, "checklist with id '%#B' not found, can't retransmit connectivity check",
&data->connect_id);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return JOB_REQUEUE_NONE;
}
@@ -980,7 +980,7 @@ retransmit_end:
break;
}
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
/* we reschedule it manually */
return JOB_REQUEUE_NONE;
@@ -1078,14 +1078,14 @@ static job_requeue_t sender(callback_data_t *data)
{
private_connect_manager_t *this = data->connect_manager;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
check_list_t *checklist;
if (get_checklist_by_id(this, data->connect_id, &checklist) != SUCCESS)
{
DBG1(DBG_IKE, "checklist with id '%#B' not found, can't send connectivity check",
&data->connect_id);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return JOB_REQUEUE_NONE;
}
@@ -1100,7 +1100,7 @@ static job_requeue_t sender(callback_data_t *data)
if (checklist->pairs->find_first(checklist->pairs,
(linked_list_match_t)match_waiting_pair, (void**)&pair) != SUCCESS)
{
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
DBG1(DBG_IKE, "no pairs in waiting state, aborting");
return JOB_REQUEUE_NONE;
}
@@ -1126,7 +1126,7 @@ static job_requeue_t sender(callback_data_t *data)
/* schedule this job again */
schedule_checks(this, checklist, ME_INTERVAL);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
/* we reschedule it manually */
return JOB_REQUEUE_NONE;
@@ -1160,7 +1160,7 @@ static job_requeue_t initiate_mediated(initiate_data_t *data)
ike_sa_t *sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, waiting_sa);
if (sa->initiate_mediated(sa, pair->local, pair->remote, checklist->connect_id) != SUCCESS)
{
- SIG_IKE(UP_FAILED, "establishing the mediated connection failed");
+ DBG1(DBG_IKE, "establishing mediated connection failed");
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, sa);
}
charon->ike_sa_manager->checkin(charon->ike_sa_manager, sa);
@@ -1345,7 +1345,7 @@ static void process_check(private_connect_manager_t *this, message_t *message)
return;
}
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
check_list_t *checklist;
if (get_checklist_by_id(this, check->connect_id, &checklist) != SUCCESS)
@@ -1353,7 +1353,7 @@ static void process_check(private_connect_manager_t *this, message_t *message)
DBG1(DBG_IKE, "checklist with id '%#B' not found",
&check->connect_id);
check_destroy(check);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return;
}
@@ -1363,7 +1363,7 @@ static void process_check(private_connect_manager_t *this, message_t *message)
DBG1(DBG_IKE, "connectivity check verification failed");
check_destroy(check);
chunk_free(&sig);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return;
}
chunk_free(&sig);
@@ -1377,7 +1377,7 @@ static void process_check(private_connect_manager_t *this, message_t *message)
process_response(this, check, checklist);
}
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
check_destroy(check);
}
@@ -1392,7 +1392,7 @@ static bool check_and_register(private_connect_manager_t *this,
initiated_t *initiated;
bool already_there = TRUE;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_initiated_by_ids(this, id, peer_id, &initiated) != SUCCESS)
{
@@ -1408,7 +1408,7 @@ static bool check_and_register(private_connect_manager_t *this,
initiated->mediated->insert_last(initiated->mediated, mediated_sa->clone(mediated_sa));
}
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return already_there;
}
@@ -1421,12 +1421,12 @@ static void check_and_initiate(private_connect_manager_t *this, ike_sa_id_t *med
{
initiated_t *initiated;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_initiated_by_ids(this, id, peer_id, &initiated) != SUCCESS)
{
DBG2(DBG_IKE, "no waiting mediated connections with '%D'", peer_id);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return;
}
@@ -1439,7 +1439,7 @@ static void check_and_initiate(private_connect_manager_t *this, ike_sa_id_t *med
}
iterator->destroy(iterator);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
}
/**
@@ -1451,20 +1451,20 @@ static status_t set_initiator_data(private_connect_manager_t *this,
{
check_list_t *checklist;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_checklist_by_id(this, connect_id, NULL) == SUCCESS)
{
DBG1(DBG_IKE, "checklist with id '%#B' already exists, aborting",
&connect_id);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return FAILED;
}
checklist = check_list_create(initiator, responder, connect_id, key, endpoints, is_initiator);
this->checklists->insert_last(this->checklists, checklist);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return SUCCESS;
}
@@ -1477,13 +1477,13 @@ static status_t set_responder_data(private_connect_manager_t *this,
{
check_list_t *checklist;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_checklist_by_id(this, connect_id, &checklist) != SUCCESS)
{
DBG1(DBG_IKE, "checklist with id '%#B' not found",
&connect_id);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return NOT_FOUND;
}
@@ -1496,7 +1496,7 @@ static status_t set_responder_data(private_connect_manager_t *this,
/* send the first check immediately */
schedule_checks(this, checklist, 0);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return SUCCESS;
}
@@ -1508,13 +1508,13 @@ static status_t stop_checks(private_connect_manager_t *this, chunk_t connect_id)
{
check_list_t *checklist;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_checklist_by_id(this, connect_id, &checklist) != SUCCESS)
{
DBG1(DBG_IKE, "checklist with id '%#B' not found",
&connect_id);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return NOT_FOUND;
}
@@ -1523,7 +1523,7 @@ static status_t stop_checks(private_connect_manager_t *this, chunk_t connect_id)
remove_checklist(this, checklist);
check_list_destroy(checklist);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return SUCCESS;
}
@@ -1533,14 +1533,14 @@ static status_t stop_checks(private_connect_manager_t *this, chunk_t connect_id)
*/
static void destroy(private_connect_manager_t *this)
{
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
this->hasher->destroy(this->hasher);
this->checklists->destroy_function(this->checklists, (void*)check_list_destroy);
this->initiated->destroy_function(this->initiated, (void*)initiated_destroy);
- pthread_mutex_unlock(&(this->mutex));
- pthread_mutex_destroy(&(this->mutex));
+ this->mutex->unlock(this->mutex);
+ this->mutex->destroy(this->mutex);
free(this);
}
@@ -1570,7 +1570,7 @@ connect_manager_t *connect_manager_create()
this->checklists = linked_list_create();
this->initiated = linked_list_create();
- pthread_mutex_init(&(this->mutex), NULL);
+ this->mutex = mutex_create(MUTEX_DEFAULT);
return (connect_manager_t*)this;
}
diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c
index 7b2608e07..d9bb01c60 100644
--- a/src/charon/sa/ike_sa.c
+++ b/src/charon/sa/ike_sa.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2006-2008 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -15,7 +15,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_sa.c 4394 2008-10-09 08:25:11Z martin $
+ * $Id: ike_sa.c 4652 2008-11-14 08:38:53Z martin $
*/
#include <sys/time.h>
@@ -23,6 +23,7 @@
#include <printf.h>
#include <sys/stat.h>
#include <errno.h>
+#include <time.h>
#include "ike_sa.h"
@@ -30,17 +31,6 @@
#include <daemon.h>
#include <utils/linked_list.h>
#include <utils/lexparser.h>
-#include <crypto/diffie_hellman.h>
-#include <crypto/prf_plus.h>
-#include <crypto/crypters/crypter.h>
-#include <crypto/hashers/hasher.h>
-#include <encoding/payloads/sa_payload.h>
-#include <encoding/payloads/nonce_payload.h>
-#include <encoding/payloads/ke_payload.h>
-#include <encoding/payloads/delete_payload.h>
-#include <encoding/payloads/transform_substructure.h>
-#include <encoding/payloads/transform_attribute.h>
-#include <encoding/payloads/ts_payload.h>
#include <sa/task_manager.h>
#include <sa/tasks/ike_init.h>
#include <sa/tasks/ike_natd.h>
@@ -72,12 +62,13 @@
#define RESOLV_CONF "/etc/resolv.conf"
#endif
-ENUM(ike_sa_state_names, IKE_CREATED, IKE_DELETING,
+ENUM(ike_sa_state_names, IKE_CREATED, IKE_DESTROYING,
"CREATED",
"CONNECTING",
"ESTABLISHED",
"REKEYING",
"DELETING",
+ "DESTROYING",
);
typedef struct private_ike_sa_t private_ike_sa_t;
@@ -128,6 +119,11 @@ struct private_ike_sa_t {
auth_info_t *other_auth;
/**
+ * Selected IKE proposal
+ */
+ proposal_t *proposal;
+
+ /**
* Juggles tasks to process messages
*/
task_manager_t *task_manager;
@@ -190,49 +186,9 @@ struct private_ike_sa_t {
linked_list_t *child_sas;
/**
- * String describing the selected IKE proposal
- */
- char *selected_proposal;
-
- /**
- * crypter for inbound traffic
- */
- crypter_t *crypter_in;
-
- /**
- * crypter for outbound traffic
- */
- crypter_t *crypter_out;
-
- /**
- * Signer for inbound traffic
- */
- signer_t *signer_in;
-
- /**
- * Signer for outbound traffic
+ * keymat of this IKE_SA
*/
- signer_t *signer_out;
-
- /**
- * Multi purpose prf, set key, use it, forget it
- */
- prf_t *prf;
-
- /**
- * Prf function for derivating keymat child SAs
- */
- prf_t *child_prf;
-
- /**
- * Key to build outging authentication data (SKp)
- */
- chunk_t skp_build;
-
- /**
- * Key to verify incoming authentication data (SKp)
- */
- chunk_t skp_verify;
+ keymat_t *keymat;
/**
* Virtual IP on local host, if any
@@ -268,34 +224,26 @@ struct private_ike_sa_t {
* NAT keep alive interval
*/
u_int32_t keepalive_interval;
-
+
/**
* Timestamps for this IKE_SA
*/
- struct {
- /** last IKE message received */
- u_int32_t inbound;
- /** last IKE message sent */
- u_int32_t outbound;
- /** when IKE_SA became established */
- u_int32_t established;
- /** when IKE_SA gets rekeyed */
- u_int32_t rekey;
- /** when IKE_SA gets reauthenticated */
- u_int32_t reauth;
- /** when IKE_SA gets deleted */
- u_int32_t delete;
- } time;
+ u_int32_t stats[STAT_MAX];
/**
* how many times we have retried so far (keyingtries)
*/
u_int32_t keyingtry;
-
+
/**
- * are we the initiator of this IKE_SA (rekeying does not affect this flag)
+ * local host address to be used for IKE, set via MIGRATE kernel message
*/
- bool ike_initiator;
+ host_t *local_host;
+
+ /**
+ * remote host address to be used for IKE, set via MIGRATE kernel message
+ */
+ host_t *remote_host;
};
/**
@@ -303,28 +251,26 @@ struct private_ike_sa_t {
*/
static time_t get_use_time(private_ike_sa_t* this, bool inbound)
{
- iterator_t *iterator;
+ enumerator_t *enumerator;
child_sa_t *child_sa;
- time_t latest = 0, use_time;
-
- iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
- while (iterator->iterate(iterator, (void**)&child_sa))
- {
- if (child_sa->get_use_time(child_sa, inbound, &use_time) == SUCCESS)
- {
- latest = max(latest, use_time);
- }
- }
- iterator->destroy(iterator);
+ time_t use_time;
if (inbound)
{
- return max(this->time.inbound, latest);
+ use_time = this->stats[STAT_INBOUND];
}
else
{
- return max(this->time.outbound, latest);
+ use_time = this->stats[STAT_OUTBOUND];
+ }
+ enumerator = this->child_sas->create_enumerator(this->child_sas);
+ while (enumerator->enumerate(enumerator, &child_sa))
+ {
+ use_time = max(use_time, child_sa->get_usetime(child_sa, inbound));
}
+ enumerator->destroy(enumerator);
+
+ return use_time;
}
/**
@@ -352,24 +298,9 @@ static char *get_name(private_ike_sa_t *this)
*/
static u_int32_t get_statistic(private_ike_sa_t *this, statistic_t kind)
{
- time_t now = time(NULL);
-
- switch (kind)
+ if (kind < STAT_MAX)
{
- case STAT_REKEY_TIME:
- if (this->time.rekey > now)
- {
- return this->time.rekey - now;
- }
- break;
- case STAT_REAUTH_TIME:
- if (this->time.reauth > now)
- {
- return this->time.reauth - now;
- }
- break;
- default:
- break;
+ return this->stats[kind];
}
return 0;
}
@@ -462,6 +393,23 @@ static auth_info_t* get_other_auth(private_ike_sa_t *this)
}
/**
+ * Implementation of ike_sa_t.get_proposal
+ */
+static proposal_t* get_proposal(private_ike_sa_t *this)
+{
+ return this->proposal;
+}
+
+/**
+ * Implementation of ike_sa_t.set_proposal
+ */
+static void set_proposal(private_ike_sa_t *this, proposal_t *proposal)
+{
+ DESTROY_IF(this->proposal);
+ this->proposal = proposal->clone(proposal);
+}
+
+/**
* Implementation of ike_sa_t.send_keepalive
*/
static void send_keepalive(private_ike_sa_t *this)
@@ -518,14 +466,6 @@ static void set_ike_cfg(private_ike_sa_t *this, ike_cfg_t *ike_cfg)
}
/**
- * Implementation of ike_sa_t.is_ike_initiator
- */
-static bool is_ike_initiator(private_ike_sa_t *this)
-{
- return this->ike_initiator;
-}
-
-/**
* Implementation of ike_sa_t.enable_extension.
*/
static void enable_extension(private_ike_sa_t *this, ike_extension_t extension)
@@ -687,47 +627,48 @@ static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
u_int32_t t;
/* calculate rekey, reauth and lifetime */
- this->time.established = time(NULL);
+ this->stats[STAT_ESTABLISHED] = time(NULL);
/* schedule rekeying if we have a time which is smaller than
* an already scheduled rekeying */
t = this->peer_cfg->get_rekey_time(this->peer_cfg);
- if (t && (this->time.rekey == 0 ||
- (this->time.rekey > t + this->time.established)))
+ if (t && (this->stats[STAT_REKEY] == 0 ||
+ (this->stats[STAT_REKEY] > t + this->stats[STAT_ESTABLISHED])))
{
- this->time.rekey = t + this->time.established;
+ this->stats[STAT_REKEY] = t + this->stats[STAT_ESTABLISHED];
job = (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, FALSE);
charon->scheduler->schedule_job(charon->scheduler,
job, t * 1000);
DBG1(DBG_IKE, "scheduling rekeying in %ds", t);
}
t = this->peer_cfg->get_reauth_time(this->peer_cfg);
- if (t && (this->time.reauth == 0 ||
- (this->time.reauth > t + this->time.established)))
+ if (t && (this->stats[STAT_REAUTH] == 0 ||
+ (this->stats[STAT_REAUTH] > t + this->stats[STAT_ESTABLISHED])))
{
- this->time.reauth = t + this->time.established;
+ this->stats[STAT_REAUTH] = t + this->stats[STAT_ESTABLISHED];
job = (job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE);
charon->scheduler->schedule_job(charon->scheduler,
job, t * 1000);
DBG1(DBG_IKE, "scheduling reauthentication in %ds", t);
}
t = this->peer_cfg->get_over_time(this->peer_cfg);
- if (this->time.rekey || this->time.reauth)
+ if (this->stats[STAT_REKEY] || this->stats[STAT_REAUTH])
{
- if (this->time.reauth == 0)
+ if (this->stats[STAT_REAUTH] == 0)
{
- this->time.delete = this->time.rekey;
+ this->stats[STAT_DELETE] = this->stats[STAT_REKEY];
}
- else if (this->time.rekey == 0)
+ else if (this->stats[STAT_REKEY] == 0)
{
- this->time.delete = this->time.reauth;
+ this->stats[STAT_DELETE] = this->stats[STAT_REAUTH];
}
else
{
- this->time.delete = min(this->time.rekey, this->time.reauth);
+ this->stats[STAT_DELETE] = min(this->stats[STAT_REKEY],
+ this->stats[STAT_REAUTH]);
}
- this->time.delete += t;
- t = this->time.delete - this->time.established;
+ this->stats[STAT_DELETE] += t;
+ t = this->stats[STAT_DELETE] - this->stats[STAT_ESTABLISHED];
job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, TRUE);
charon->scheduler->schedule_job(charon->scheduler, job,
t * 1000);
@@ -750,7 +691,7 @@ static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
default:
break;
}
-
+ charon->bus->ike_state_change(charon->bus, &this->public, state);
this->state = state;
}
@@ -771,6 +712,14 @@ static void reset(private_ike_sa_t *this)
}
/**
+ * Implementation of ike_sa_t.get_keymat
+ */
+static keymat_t* get_keymat(private_ike_sa_t *this)
+{
+ return this->keymat;
+}
+
+/**
* Implementation of ike_sa_t.set_virtual_ip
*/
static void set_virtual_ip(private_ike_sa_t *this, bool local, host_t *ip)
@@ -925,8 +874,14 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
{
- child_sa->update_hosts(child_sa, this->my_host, this->other_host,
- has_condition(this, COND_NAT_ANY));
+ if (child_sa->update_hosts(child_sa, this->my_host,
+ this->other_host, this->my_virtual_ip,
+ has_condition(this, COND_NAT_ANY)) == NOT_SUPPORTED)
+ {
+ this->public.rekey_child_sa(&this->public,
+ child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE));
+ }
}
iterator->destroy(iterator);
}
@@ -938,9 +893,11 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
static status_t generate_message(private_ike_sa_t *this, message_t *message,
packet_t **packet)
{
- this->time.outbound = time(NULL);
+ this->stats[STAT_OUTBOUND] = time(NULL);
message->set_ike_sa_id(message, this->ike_sa_id);
- return message->generate(message, this->crypter_out, this->signer_out, packet);
+ return message->generate(message,
+ this->keymat->get_crypter(this->keymat, FALSE),
+ this->keymat->get_signer(this->keymat, FALSE), packet);
}
/**
@@ -978,6 +935,17 @@ static void send_notify_response(private_ike_sa_t *this, message_t *request,
response->destroy(response);
}
+/**
+ * Implementation of ike_sa_t.set_kmaddress.
+ */
+static void set_kmaddress(private_ike_sa_t *this, host_t *local, host_t *remote)
+{
+ DESTROY_IF(this->local_host);
+ DESTROY_IF(this->remote_host);
+ this->local_host = local->clone(local);
+ this->remote_host = remote->clone(remote);
+}
+
#ifdef ME
/**
* Implementation of ike_sa_t.act_as_mediation_server.
@@ -1082,26 +1050,42 @@ static void resolve_hosts(private_ike_sa_t *this)
{
host_t *host;
- host = host_create_from_dns(this->ike_cfg->get_other_addr(this->ike_cfg),
- 0, IKEV2_UDP_PORT);
+ if (this->remote_host)
+ {
+ host = this->remote_host->clone(this->remote_host);
+ host->set_port(host, IKEV2_UDP_PORT);
+ }
+ else
+ {
+ host = host_create_from_dns(this->ike_cfg->get_other_addr(this->ike_cfg),
+ 0, IKEV2_UDP_PORT);
+ }
if (host)
{
set_other_host(this, host);
}
- host = host_create_from_dns(this->ike_cfg->get_my_addr(this->ike_cfg),
- this->my_host->get_family(this->my_host),
- IKEV2_UDP_PORT);
-
- if (host && host->is_anyaddr(host) &&
- !this->other_host->is_anyaddr(this->other_host))
+ if (this->local_host)
{
- host->destroy(host);
- host = charon->kernel_interface->get_source_addr(
- charon->kernel_interface, this->other_host, NULL);
- if (host)
+ host = this->local_host->clone(this->local_host);
+ host->set_port(host, IKEV2_UDP_PORT);
+ }
+ else
+ {
+ host = host_create_from_dns(this->ike_cfg->get_my_addr(this->ike_cfg),
+ this->my_host->get_family(this->my_host),
+ IKEV2_UDP_PORT);
+
+ if (host && host->is_anyaddr(host) &&
+ !this->other_host->is_anyaddr(this->other_host))
{
- host->set_port(host, IKEV2_UDP_PORT);
+ host->destroy(host);
+ host = charon->kernel_interface->get_source_addr(
+ charon->kernel_interface, this->other_host, NULL);
+ if (host)
+ {
+ host->set_port(host, IKEV2_UDP_PORT);
+ }
}
}
if (host)
@@ -1128,12 +1112,11 @@ static status_t initiate_with_reqid(private_ike_sa_t *this, child_cfg_t *child_c
)
{
child_cfg->destroy(child_cfg);
- SIG_IKE(UP_START, "initiating IKE_SA");
- SIG_IKE(UP_FAILED, "unable to initiate to %%any");
+ DBG1(DBG_IKE, "unable to initiate to %%any");
return DESTROY_ME;
}
- this->ike_initiator = TRUE;
+ set_condition(this, COND_ORIGINAL_INITIATOR, TRUE);
task = (task_t*)ike_init_create(&this->public, TRUE, NULL);
this->task_manager->queue_task(this->task_manager, task);
@@ -1163,10 +1146,12 @@ static status_t initiate_with_reqid(private_ike_sa_t *this, child_cfg_t *child_c
#ifdef ME
if (this->peer_cfg->is_mediation(this->peer_cfg))
{
- /* mediation connection */
if (this->state == IKE_ESTABLISHED)
- { /* FIXME: we should try to find a better solution to this */
- SIG_CHD(UP_SUCCESS, NULL, "mediation connection is already up and running");
+ {
+ /* mediation connection is already established, retrigger state change
+ * to notify bus listeners */
+ DBG1(DBG_IKE, "mediation connection is already up");
+ set_state(this, IKE_ESTABLISHED);
}
DESTROY_IF(child_cfg);
}
@@ -1216,9 +1201,8 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
if (this->state == IKE_DELETING)
{
- SIG_CHD(UP_START, NULL, "acquiring CHILD_SA on kernel request");
- SIG_CHD(UP_FAILED, NULL, "acquiring CHILD_SA {reqid %d} failed: "
- "IKE_SA is deleting", reqid);
+ DBG1(DBG_IKE, "acquiring CHILD_SA {reqid %d} failed: "
+ "IKE_SA is deleting", reqid);
return FAILED;
}
@@ -1235,9 +1219,8 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
iterator->destroy(iterator);
if (!child_sa)
{
- SIG_CHD(UP_START, NULL, "acquiring CHILD_SA on kernel request");
- SIG_CHD(UP_FAILED, NULL, "acquiring CHILD_SA {reqid %d} failed: "
- "CHILD_SA not found", reqid);
+ DBG1(DBG_IKE, "acquiring CHILD_SA {reqid %d} failed: "
+ "CHILD_SA not found", reqid);
return FAILED;
}
@@ -1258,8 +1241,6 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
host_t *me, *other;
status_t status;
- SIG_CHD(ROUTE_START, NULL, "routing CHILD_SA");
-
/* check if not already routed*/
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
@@ -1268,7 +1249,7 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
streq(child_sa->get_name(child_sa), child_cfg->get_name(child_cfg)))
{
iterator->destroy(iterator);
- SIG_CHD(ROUTE_FAILED, child_sa, "CHILD_SA with such a config already routed");
+ DBG1(DBG_IKE, "routing CHILD_SA failed: already routed");
return FAILED;
}
}
@@ -1278,8 +1259,8 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
{
case IKE_DELETING:
case IKE_REKEYING:
- SIG_CHD(ROUTE_FAILED, NULL,
- "unable to route CHILD_SA, as its IKE_SA gets deleted");
+ DBG1(DBG_IKE, "routing CHILD_SA failed: IKE_SA is %N",
+ ike_sa_state_names, this->state);
return FAILED;
case IKE_CREATED:
case IKE_CONNECTING:
@@ -1291,8 +1272,8 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
resolve_hosts(this);
/* install kernel policies */
- child_sa = child_sa_create(this->my_host, this->other_host, this->my_id,
- this->other_id, child_cfg, 0, FALSE);
+ child_sa = child_sa_create(this->my_host, this->other_host,
+ child_cfg, 0, FALSE);
me = this->my_host;
if (this->my_virtual_ip)
{
@@ -1306,18 +1287,21 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, me);
other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, other);
+
status = child_sa->add_policies(child_sa, my_ts, other_ts,
- child_cfg->get_mode(child_cfg), PROTO_NONE);
+ child_cfg->get_mode(child_cfg), PROTO_NONE);
+
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
if (status == SUCCESS)
{
this->child_sas->insert_last(this->child_sas, child_sa);
- SIG_CHD(ROUTE_SUCCESS, child_sa, "CHILD_SA routed");
+ DBG1(DBG_IKE, "CHILD_SA routed");
}
else
{
- SIG_CHD(ROUTE_FAILED, child_sa, "routing CHILD_SA failed");
+ child_sa->destroy(child_sa);
+ DBG1(DBG_IKE, "routing CHILD_SA failed");
}
return status;
}
@@ -1331,8 +1315,6 @@ static status_t unroute(private_ike_sa_t *this, u_int32_t reqid)
child_sa_t *child_sa;
bool found = FALSE;
- SIG_CHD(UNROUTE_START, NULL, "unrouting CHILD_SA");
-
/* find CHILD_SA in ROUTED state */
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
@@ -1341,7 +1323,7 @@ static status_t unroute(private_ike_sa_t *this, u_int32_t reqid)
child_sa->get_reqid(child_sa) == reqid)
{
iterator->remove(iterator);
- SIG_CHD(UNROUTE_SUCCESS, child_sa, "CHILD_SA unrouted");
+ DBG1(DBG_IKE, "CHILD_SA unrouted");
child_sa->destroy(child_sa);
found = TRUE;
break;
@@ -1351,7 +1333,7 @@ static status_t unroute(private_ike_sa_t *this, u_int32_t reqid)
if (!found)
{
- SIG_CHD(UNROUTE_FAILED, NULL, "CHILD_SA to unroute not found");
+ DBG1(DBG_IKE, "unrouting CHILD_SA failed: reqid %d not found", reqid);
return FAILED;
}
/* if we are not established, and we have no more routed childs, remove whole SA */
@@ -1362,6 +1344,7 @@ static status_t unroute(private_ike_sa_t *this, u_int32_t reqid)
}
return SUCCESS;
}
+
/**
* Implementation of ike_sa_t.process_message.
*/
@@ -1372,7 +1355,9 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
is_request = message->get_request(message);
- status = message->parse_body(message, this->crypter_in, this->signer_in);
+ status = message->parse_body(message,
+ this->keymat->get_crypter(this->keymat, TRUE),
+ this->keymat->get_signer(this->keymat, TRUE));
if (status != SUCCESS)
{
@@ -1431,7 +1416,7 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
me = message->get_destination(message);
other = message->get_source(message);
-
+
/* if this IKE_SA is virgin, we check for a config */
if (this->ike_cfg == NULL)
{
@@ -1451,7 +1436,7 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
charon->scheduler->schedule_job(charon->scheduler, job,
HALF_OPEN_IKE_SA_TIMEOUT);
}
- this->time.inbound = time(NULL);
+ this->stats[STAT_INBOUND] = time(NULL);
/* check if message is trustworthy, and update host information */
if (this->state == IKE_CREATED || this->state == IKE_CONNECTING ||
message->get_exchange_type(message) != IKE_SA_INIT)
@@ -1510,38 +1495,6 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
}
/**
- * Implementation of ike_sa_t.get_prf.
- */
-static prf_t *get_prf(private_ike_sa_t *this)
-{
- return this->prf;
-}
-
-/**
- * Implementation of ike_sa_t.get_prf.
- */
-static prf_t *get_child_prf(private_ike_sa_t *this)
-{
- return this->child_prf;
-}
-
-/**
- * Implementation of ike_sa_t.get_skp_bild
- */
-static chunk_t get_skp_build(private_ike_sa_t *this)
-{
- return this->skp_build;
-}
-
-/**
- * Implementation of ike_sa_t.get_skp_verify
- */
-static chunk_t get_skp_verify(private_ike_sa_t *this)
-{
- return this->skp_verify;
-}
-
-/**
* Implementation of ike_sa_t.get_id.
*/
static ike_sa_id_t* get_id(private_ike_sa_t *this)
@@ -1601,230 +1554,6 @@ static void set_eap_identity(private_ike_sa_t *this, identification_t *id)
}
/**
- * Implementation of ike_sa_t.derive_keys.
- */
-static status_t derive_keys(private_ike_sa_t *this,
- proposal_t *proposal, chunk_t secret,
- chunk_t nonce_i, chunk_t nonce_r,
- bool initiator, prf_t *child_prf, prf_t *old_prf)
-{
- prf_plus_t *prf_plus;
- chunk_t skeyseed, key, full_nonce, fixed_nonce, prf_plus_seed;
- u_int16_t alg, key_size;
- crypter_t *crypter_i, *crypter_r;
- signer_t *signer_i, *signer_r;
- u_int8_t spi_i_buf[sizeof(u_int64_t)], spi_r_buf[sizeof(u_int64_t)];
- chunk_t spi_i = chunk_from_buf(spi_i_buf);
- chunk_t spi_r = chunk_from_buf(spi_r_buf);
-
- /* Create SAs general purpose PRF first, we may use it here */
- if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
- {
- DBG1(DBG_IKE, "no %N selected",
- transform_type_names, PSEUDO_RANDOM_FUNCTION);
- return FAILED;
- }
- this->prf = lib->crypto->create_prf(lib->crypto, alg);
- if (this->prf == NULL)
- {
- DBG1(DBG_IKE, "%N %N not supported!",
- transform_type_names, PSEUDO_RANDOM_FUNCTION,
- pseudo_random_function_names, alg);
- return FAILED;
- }
- DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &secret);
- /* full nonce is used as seed for PRF+ ... */
- full_nonce = chunk_cat("cc", nonce_i, nonce_r);
- /* but the PRF may need a fixed key which only uses the first bytes of
- * the nonces. */
- switch (alg)
- {
- case PRF_AES128_XCBC:
- /* while rfc4434 defines variable keys for AES-XCBC, rfc3664 does
- * not and therefore fixed key semantics apply to XCBC for key
- * derivation. */
- nonce_i.len = min(nonce_i.len, this->prf->get_key_size(this->prf)/2);
- nonce_r.len = min(nonce_r.len, this->prf->get_key_size(this->prf)/2);
- break;
- default:
- /* all other algorithms use variable key length, full nonce */
- break;
- }
- fixed_nonce = chunk_cat("cc", nonce_i, nonce_r);
- *((u_int64_t*)spi_i.ptr) = this->ike_sa_id->get_initiator_spi(this->ike_sa_id);
- *((u_int64_t*)spi_r.ptr) = this->ike_sa_id->get_responder_spi(this->ike_sa_id);
- prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r);
-
- /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
- *
- * if we are rekeying, SKEYSEED is built on another way
- */
- if (child_prf == NULL) /* not rekeying */
- {
- /* SKEYSEED = prf(Ni | Nr, g^ir) */
- this->prf->set_key(this->prf, fixed_nonce);
- this->prf->allocate_bytes(this->prf, secret, &skeyseed);
- DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
- this->prf->set_key(this->prf, skeyseed);
- chunk_free(&skeyseed);
- chunk_free(&secret);
- prf_plus = prf_plus_create(this->prf, prf_plus_seed);
- }
- else
- {
- /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr)
- * use OLD SAs PRF functions for both prf_plus and prf */
- secret = chunk_cat("mc", secret, full_nonce);
- child_prf->allocate_bytes(child_prf, secret, &skeyseed);
- DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
- old_prf->set_key(old_prf, skeyseed);
- chunk_free(&skeyseed);
- chunk_free(&secret);
- prf_plus = prf_plus_create(old_prf, prf_plus_seed);
- }
- chunk_free(&full_nonce);
- chunk_free(&fixed_nonce);
- chunk_free(&prf_plus_seed);
-
- /* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */
-
- /* SK_d is used for generating CHILD_SA key mat => child_prf */
- proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL);
- this->child_prf = lib->crypto->create_prf(lib->crypto, alg);
- key_size = this->child_prf->get_key_size(this->child_prf);
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_d secret %B", &key);
- this->child_prf->set_key(this->child_prf, key);
- chunk_free(&key);
-
- /* SK_ai/SK_ar used for integrity protection => signer_in/signer_out */
- if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL))
- {
- DBG1(DBG_IKE, "no %N selected",
- transform_type_names, INTEGRITY_ALGORITHM);
- return FAILED;
- }
- signer_i = lib->crypto->create_signer(lib->crypto, alg);
- signer_r = lib->crypto->create_signer(lib->crypto, alg);
- if (signer_i == NULL || signer_r == NULL)
- {
- DBG1(DBG_IKE, "%N %N not supported!",
- transform_type_names, INTEGRITY_ALGORITHM,
- integrity_algorithm_names ,alg);
- prf_plus->destroy(prf_plus);
- return FAILED;
- }
- key_size = signer_i->get_key_size(signer_i);
-
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_ai secret %B", &key);
- signer_i->set_key(signer_i, key);
- chunk_free(&key);
-
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_ar secret %B", &key);
- signer_r->set_key(signer_r, key);
- chunk_free(&key);
-
- if (initiator)
- {
- this->signer_in = signer_r;
- this->signer_out = signer_i;
- }
- else
- {
- this->signer_in = signer_i;
- this->signer_out = signer_r;
- }
-
- /* SK_ei/SK_er used for encryption => crypter_in/crypter_out */
- if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &key_size))
- {
- DBG1(DBG_IKE, "no %N selected",
- transform_type_names, ENCRYPTION_ALGORITHM);
- prf_plus->destroy(prf_plus);
- return FAILED;
- }
- crypter_i = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
- crypter_r = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
- if (crypter_i == NULL || crypter_r == NULL)
- {
- DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
- transform_type_names, ENCRYPTION_ALGORITHM,
- encryption_algorithm_names, alg, key_size);
- prf_plus->destroy(prf_plus);
- return FAILED;
- }
- key_size = crypter_i->get_key_size(crypter_i);
-
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_ei secret %B", &key);
- crypter_i->set_key(crypter_i, key);
- chunk_free(&key);
-
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_er secret %B", &key);
- crypter_r->set_key(crypter_r, key);
- chunk_free(&key);
-
- if (initiator)
- {
- this->crypter_in = crypter_r;
- this->crypter_out = crypter_i;
- }
- else
- {
- this->crypter_in = crypter_i;
- this->crypter_out = crypter_r;
- }
-
- /* SK_pi/SK_pr used for authentication => stored for later */
- key_size = this->prf->get_key_size(this->prf);
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_pi secret %B", &key);
- if (initiator)
- {
- this->skp_build = key;
- }
- else
- {
- this->skp_verify = key;
- }
- prf_plus->allocate_bytes(prf_plus, key_size, &key);
- DBG4(DBG_IKE, "Sk_pr secret %B", &key);
- if (initiator)
- {
- this->skp_verify = key;
- }
- else
- {
- this->skp_build = key;
- }
-
- /* all done, prf_plus not needed anymore */
- prf_plus->destroy(prf_plus);
-
- return SUCCESS;
-}
-
-/**
- * Implementation of ike_sa_t.get_proposal.
- */
-static char* get_proposal(private_ike_sa_t *this)
-{
- return this->selected_proposal;
-}
-
-/**
- * Implementation of ike_sa_t.set_proposal.
- */
-static void set_proposal(private_ike_sa_t *this, char *proposal)
-{
- free(this->selected_proposal);
- this->selected_proposal = strdup(proposal);
-}
-
-/**
* Implementation of ike_sa_t.add_child_sa.
*/
static void add_child_sa(private_ike_sa_t *this, child_sa_t *child_sa)
@@ -1939,10 +1668,10 @@ static status_t delete_(private_ike_sa_t *this)
this->task_manager->queue_task(this->task_manager, &ike_delete->task);
return this->task_manager->initiate(this->task_manager);
case IKE_CREATED:
- SIG_IKE(DOWN_SUCCESS, "deleting unestablished IKE_SA");
+ DBG1(DBG_IKE, "deleting unestablished IKE_SA");
break;
default:
- SIG_IKE(DOWN_SUCCESS, "destroying IKE_SA in state %N "
+ DBG1(DBG_IKE, "destroying IKE_SA in state %N "
"without notification", ike_sa_state_names, this->state);
break;
}
@@ -1972,7 +1701,7 @@ static status_t reauth(private_ike_sa_t *this)
/* we can't reauthenticate as responder when we use EAP or virtual IPs.
* If the peer does not support RFC4478, there is no way to keep the
* IKE_SA up. */
- if (!this->ike_initiator)
+ if (!has_condition(this, COND_ORIGINAL_INITIATOR))
{
DBG1(DBG_IKE, "initiator did not reauthenticate as requested");
if (this->other_virtual_ip != NULL ||
@@ -1985,7 +1714,8 @@ static status_t reauth(private_ike_sa_t *this)
{
time_t now = time(NULL);
- DBG1(DBG_IKE, "IKE_SA will timeout in %#V", &now, &this->time.delete);
+ DBG1(DBG_IKE, "IKE_SA will timeout in %#V",
+ &now, &this->stats[STAT_DELETE]);
return FAILED;
}
else
@@ -2049,7 +1779,7 @@ static status_t reestablish(private_ike_sa_t *this)
}
/* check if we are able to reestablish this IKE_SA */
- if (!this->ike_initiator &&
+ if (!has_condition(this, COND_ORIGINAL_INITIATOR) &&
(this->other_virtual_ip != NULL ||
has_condition(this, COND_EAP_AUTHENTICATED)
#ifdef ME
@@ -2133,7 +1863,7 @@ static status_t reestablish(private_ike_sa_t *this)
*/
static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
{
- this->time.outbound = time(NULL);
+ this->stats[STAT_OUTBOUND] = time(NULL);
if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS)
{
/* send a proper signal to brief interested bus listeners */
@@ -2146,19 +1876,19 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
this->keyingtry++;
if (tries == 0 || tries > this->keyingtry)
{
- SIG_IKE(UP_FAILED, "peer not responding, trying again "
- "(%d/%d) in background ", this->keyingtry + 1, tries);
+ DBG1(DBG_IKE, "peer not responding, trying again (%d/%d)",
+ this->keyingtry + 1, tries);
reset(this);
return this->task_manager->initiate(this->task_manager);
}
- SIG_IKE(UP_FAILED, "establishing IKE_SA failed, peer not responding");
+ DBG1(DBG_IKE, "establishing IKE_SA failed, peer not responding");
break;
}
case IKE_DELETING:
- SIG_IKE(DOWN_FAILED, "proper IKE_SA delete failed, peer not responding");
+ DBG1(DBG_IKE, "proper IKE_SA delete failed, peer not responding");
break;
case IKE_REKEYING:
- SIG_IKE(REKEY_FAILED, "rekeying IKE_SA failed, peer not responding");
+ DBG1(DBG_IKE, "rekeying IKE_SA failed, peer not responding");
/* FALL */
default:
reestablish(this);
@@ -2184,9 +1914,10 @@ static void set_auth_lifetime(private_ike_sa_t *this, u_int32_t lifetime)
charon->processor->queue_job(charon->processor,
(job_t*)rekey_ike_sa_job_create(this->ike_sa_id, TRUE));
}
- else if (this->time.reauth == 0 || this->time.reauth > reauth_time)
+ else if (this->stats[STAT_REAUTH] == 0 ||
+ this->stats[STAT_REAUTH] > reauth_time)
{
- this->time.reauth = reauth_time;
+ this->stats[STAT_REAUTH] = reauth_time;
DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, scheduling reauthentication"
" in %ds", lifetime, lifetime - reduction);
charon->scheduler->schedule_job(charon->scheduler,
@@ -2196,7 +1927,7 @@ static void set_auth_lifetime(private_ike_sa_t *this, u_int32_t lifetime)
else
{
DBG1(DBG_IKE, "received AUTH_LIFETIME of %ds, reauthentication already "
- "scheduled in %ds", lifetime, this->time.reauth - time(NULL));
+ "scheduled in %ds", lifetime, this->stats[STAT_REAUTH] - time(NULL));
}
}
@@ -2275,7 +2006,6 @@ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other)
this->other_host = other->other_host->clone(other->other_host);
this->my_id = other->my_id->clone(other->my_id);
this->other_id = other->other_id->clone(other->other_id);
- this->ike_initiator = other->ike_initiator;
/* apply virtual assigned IPs... */
if (other->my_virtual_ip)
@@ -2296,7 +2026,7 @@ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other)
this->dns_servers->insert_first(this->dns_servers, ip);
}
- /* inherit NAT-T conditions */
+ /* inherit all conditions */
this->conditions = other->conditions;
if (this->conditions & COND_NAT_HERE)
{
@@ -2326,14 +2056,14 @@ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other)
this->task_manager->adopt_tasks(this->task_manager, other->task_manager);
/* reauthentication timeout survives a rekeying */
- if (other->time.reauth)
+ if (other->stats[STAT_REAUTH])
{
time_t reauth, delete, now = time(NULL);
- this->time.reauth = other->time.reauth;
- reauth = this->time.reauth - now;
+ this->stats[STAT_REAUTH] = other->stats[STAT_REAUTH];
+ reauth = this->stats[STAT_REAUTH] - now;
delete = reauth + this->peer_cfg->get_over_time(this->peer_cfg);
- this->time.delete = this->time.reauth + delete;
+ this->stats[STAT_DELETE] = this->stats[STAT_REAUTH] + delete;
DBG1(DBG_IKE, "rescheduling reauthentication in %ds after rekeying, "
"lifetime reduced to %ds", reauth, delete);
charon->scheduler->schedule_job(charon->scheduler,
@@ -2421,7 +2151,7 @@ static void remove_dns_servers(private_ike_sa_t *this)
if (!found)
{
/* write line untouched back to file */
- fwrite(orig_line.ptr, orig_line.len, 1, file);
+ ignore_result(fwrite(orig_line.ptr, orig_line.len, 1, file));
fprintf(file, "\n");
}
}
@@ -2475,7 +2205,7 @@ static void add_dns_server(private_ike_sa_t *this, host_t *dns)
{
this->dns_servers->insert_last(this->dns_servers, dns->clone(dns));
}
- fwrite(contents.ptr, contents.len, 1, file);
+ ignore_result(fwrite(contents.ptr, contents.len, 1, file));
fclose(file);
}
@@ -2485,19 +2215,17 @@ static void add_dns_server(private_ike_sa_t *this, host_t *dns)
*/
static void destroy(private_ike_sa_t *this)
{
+ charon->bus->set_sa(charon->bus, &this->public);
+
+ set_state(this, IKE_DESTROYING);
+
this->child_sas->destroy_offset(this->child_sas, offsetof(child_sa_t, destroy));
- this->task_manager->destroy(this->task_manager);
+ /* unset SA after here to avoid usage by the listeners */
+ charon->bus->set_sa(charon->bus, NULL);
- DESTROY_IF(this->crypter_in);
- DESTROY_IF(this->crypter_out);
- DESTROY_IF(this->signer_in);
- DESTROY_IF(this->signer_out);
- DESTROY_IF(this->prf);
- DESTROY_IF(this->child_prf);
- chunk_free(&this->skp_verify);
- chunk_free(&this->skp_build);
- free(this->selected_proposal);
+ this->task_manager->destroy(this->task_manager);
+ this->keymat->destroy(this->keymat);
if (this->my_virtual_ip)
{
@@ -2535,12 +2263,15 @@ static void destroy(private_ike_sa_t *this)
DESTROY_IF(this->other_host);
DESTROY_IF(this->my_id);
DESTROY_IF(this->other_id);
+ DESTROY_IF(this->local_host);
+ DESTROY_IF(this->remote_host);
DESTROY_IF(this->eap_identity);
DESTROY_IF(this->ike_cfg);
DESTROY_IF(this->peer_cfg);
DESTROY_IF(this->my_auth);
DESTROY_IF(this->other_auth);
+ DESTROY_IF(this->proposal);
this->ike_sa_id->destroy(this->ike_sa_id);
free(this);
@@ -2570,6 +2301,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.set_peer_cfg = (void (*)(ike_sa_t*,peer_cfg_t*))set_peer_cfg;
this->public.get_my_auth = (auth_info_t*(*)(ike_sa_t*))get_my_auth;
this->public.get_other_auth = (auth_info_t*(*)(ike_sa_t*))get_other_auth;
+ this->public.get_proposal = (proposal_t*(*)(ike_sa_t*))get_proposal;
+ this->public.set_proposal = (void(*)(ike_sa_t*, proposal_t *proposal))set_proposal;
this->public.get_id = (ike_sa_id_t* (*)(ike_sa_t*)) get_id;
this->public.get_my_host = (host_t* (*)(ike_sa_t*)) get_my_host;
this->public.set_my_host = (void (*)(ike_sa_t*,host_t*)) set_my_host;
@@ -2588,7 +2321,6 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.has_condition = (bool (*)(ike_sa_t*,ike_condition_t)) has_condition;
this->public.set_pending_updates = (void(*)(ike_sa_t*, u_int32_t updates))set_pending_updates;
this->public.get_pending_updates = (u_int32_t(*)(ike_sa_t*))get_pending_updates;
- this->public.is_ike_initiator = (bool (*)(ike_sa_t*))is_ike_initiator;
this->public.create_additional_address_iterator = (iterator_t*(*)(ike_sa_t*))create_additional_address_iterator;
this->public.add_additional_address = (void(*)(ike_sa_t*, host_t *host))add_additional_address;
this->public.has_mapping_changed = (bool(*)(ike_sa_t*, chunk_t hash))has_mapping_changed;
@@ -2597,13 +2329,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.destroy = (void (*)(ike_sa_t*))destroy;
this->public.send_dpd = (status_t (*)(ike_sa_t*)) send_dpd;
this->public.send_keepalive = (void (*)(ike_sa_t*)) send_keepalive;
- this->public.get_prf = (prf_t* (*)(ike_sa_t*)) get_prf;
- this->public.get_child_prf = (prf_t* (*)(ike_sa_t *)) get_child_prf;
- this->public.get_skp_verify = (chunk_t (*)(ike_sa_t *)) get_skp_verify;
- this->public.get_skp_build = (chunk_t (*)(ike_sa_t *)) get_skp_build;
- this->public.derive_keys = (status_t (*)(ike_sa_t *,proposal_t*,chunk_t,chunk_t,chunk_t,bool,prf_t*,prf_t*)) derive_keys;
- this->public.get_proposal = (char* (*)(ike_sa_t*)) get_proposal;
- this->public.set_proposal = (void (*)(ike_sa_t*,char*)) set_proposal;
+ this->public.get_keymat = (keymat_t*(*)(ike_sa_t*))get_keymat;
this->public.add_child_sa = (void (*)(ike_sa_t*,child_sa_t*)) add_child_sa;
this->public.get_child_sa = (child_sa_t* (*)(ike_sa_t*,protocol_id_t,u_int32_t,bool)) get_child_sa;
this->public.create_child_sa_iterator = (iterator_t* (*)(ike_sa_t*)) create_child_sa_iterator;
@@ -2622,6 +2348,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.set_virtual_ip = (void (*)(ike_sa_t*,bool,host_t*))set_virtual_ip;
this->public.get_virtual_ip = (host_t* (*)(ike_sa_t*,bool))get_virtual_ip;
this->public.add_dns_server = (void (*)(ike_sa_t*,host_t*))add_dns_server;
+ this->public.set_kmaddress = (void (*)(ike_sa_t*,host_t*,host_t*))set_kmaddress;
#ifdef ME
this->public.act_as_mediation_server = (void (*)(ike_sa_t*)) act_as_mediation_server;
this->public.get_server_reflexive_host = (host_t* (*)(ike_sa_t*)) get_server_reflexive_host;
@@ -2637,34 +2364,24 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
/* initialize private fields */
this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
this->child_sas = linked_list_create();
- this->my_host = host_create_from_string("0.0.0.0", IKEV2_UDP_PORT);
- this->other_host = host_create_from_string("0.0.0.0", IKEV2_UDP_PORT);
+ this->my_host = host_create_any(AF_INET);
+ this->other_host = host_create_any(AF_INET);
this->my_id = identification_create_from_encoding(ID_ANY, chunk_empty);
this->other_id = identification_create_from_encoding(ID_ANY, chunk_empty);
this->eap_identity = NULL;
this->extensions = 0;
this->conditions = 0;
- this->selected_proposal = NULL;
- this->crypter_in = NULL;
- this->crypter_out = NULL;
- this->signer_in = NULL;
- this->signer_out = NULL;
- this->prf = NULL;
- this->skp_verify = chunk_empty;
- this->skp_build = chunk_empty;
- this->child_prf = NULL;
+ this->keymat = keymat_create(ike_sa_id->is_initiator(ike_sa_id));
this->state = IKE_CREATED;
this->keepalive_interval = lib->settings->get_time(lib->settings,
"charon.keep_alive", KEEPALIVE_INTERVAL);
- this->time.inbound = this->time.outbound = time(NULL);
- this->time.established = 0;
- this->time.rekey = 0;
- this->time.reauth = 0;
- this->time.delete = 0;
+ memset(this->stats, 0, sizeof(this->stats));
+ this->stats[STAT_INBOUND] = this->stats[STAT_OUTBOUND] = time(NULL);
this->ike_cfg = NULL;
this->peer_cfg = NULL;
this->my_auth = auth_info_create();
this->other_auth = auth_info_create();
+ this->proposal = NULL;
this->task_manager = task_manager_create(&this->public);
this->unique_id = ++unique_id;
this->my_virtual_ip = NULL;
@@ -2674,7 +2391,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->nat_detection_dest = chunk_empty;
this->pending_updates = 0;
this->keyingtry = 0;
- this->ike_initiator = FALSE;
+ this->local_host = NULL;
+ this->remote_host = NULL;
#ifdef ME
this->is_mediation_server = FALSE;
this->server_reflexive_host = NULL;
diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h
index 717d41647..5aa458704 100644
--- a/src/charon/sa/ike_sa.h
+++ b/src/charon/sa/ike_sa.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2006-2008 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -15,7 +15,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_sa.h 4368 2008-10-06 13:37:04Z martin $
+ * $Id: ike_sa.h 4640 2008-11-12 16:07:17Z martin $
*/
/**
@@ -38,9 +38,7 @@ typedef struct ike_sa_t ike_sa_t;
#include <sa/ike_sa_id.h>
#include <sa/child_sa.h>
#include <sa/tasks/task.h>
-#include <crypto/prfs/prf.h>
-#include <crypto/crypters/crypter.h>
-#include <crypto/signers/signer.h>
+#include <sa/keymat.h>
#include <config/peer_cfg.h>
#include <config/ike_cfg.h>
#include <credentials/auth_info.h>
@@ -110,32 +108,41 @@ enum ike_condition_t {
* Faking NAT to enforce UDP encapsulation
*/
COND_NAT_FAKE = (1<<3),
-
+
/**
* peer has ben authenticated using EAP
*/
COND_EAP_AUTHENTICATED = (1<<4),
-
+
/**
* received a certificate request from the peer
*/
COND_CERTREQ_SEEN = (1<<5),
+
+ /**
+ * Local peer is the "original" IKE initiator. Unaffected from rekeying.
+ */
+ COND_ORIGINAL_INITIATOR = (1<<6),
};
/**
- * Information and statistics to query from an SA
+ * Timing information and statistics to query from an SA
*/
enum statistic_t {
-
- /**
- * Relative time for scheduled rekeying
- */
- STAT_REKEY_TIME,
-
- /**
- * Relative time for scheduled reauthentication
- */
- STAT_REAUTH_TIME,
+ /** Timestamp of SA establishement */
+ STAT_ESTABLISHED = 0,
+ /** Timestamp of scheudled rekeying */
+ STAT_REKEY,
+ /** Timestamp of scheudled reauthentication */
+ STAT_REAUTH,
+ /** Timestamp of scheudled delete */
+ STAT_DELETE,
+ /** Timestamp of last inbound IKE packet */
+ STAT_INBOUND,
+ /** Timestamp of last outbound IKE packet */
+ STAT_OUTBOUND,
+
+ STAT_MAX
};
/**
@@ -201,6 +208,11 @@ enum ike_sa_state_t {
* IKE_SA is in progress of deletion
*/
IKE_DELETING,
+
+ /**
+ * IKE_SA object gets destroyed
+ */
+ IKE_DESTROYING,
};
/**
@@ -388,6 +400,20 @@ struct ike_sa_t {
auth_info_t* (*get_other_auth)(ike_sa_t *this);
/**
+ * Get the selected proposal of this IKE_SA.
+ *
+ * @return selected proposal
+ */
+ proposal_t* (*get_proposal)(ike_sa_t *this);
+
+ /**
+ * Set the proposal selected for this IKE_SA.
+ *
+ * @param selected proposal
+ */
+ void (*set_proposal)(ike_sa_t *this, proposal_t *proposal);
+
+ /**
* Add an additional address for the peer.
*
* In MOBIKE, a peer may transmit additional addresses where it is
@@ -462,13 +488,6 @@ struct ike_sa_t {
*/
void (*set_pending_updates)(ike_sa_t *this, u_int32_t updates);
- /**
- * Check if we are the original initiator of this IKE_SA (rekeying does not
- * change this flag).
- */
- bool (*is_ike_initiator)(ike_sa_t *this);
-
-
#ifdef ME
/**
* Activate mediation server functionality for this IKE_SA.
@@ -705,70 +724,13 @@ struct ike_sa_t {
* was sent.
*/
void (*send_keepalive) (ike_sa_t *this);
-
- /**
- * Derive all keys and create the transforms for IKE communication.
- *
- * Keys are derived using the diffie hellman secret, nonces and internal
- * stored SPIs.
- * Key derivation differs when an IKE_SA is set up to replace an
- * existing IKE_SA (rekeying). The SK_d key from the old IKE_SA
- * is included in the derivation process.
- *
- * @param proposal proposal which contains algorithms to use
- * @param secret secret derived from DH exchange, gets freed
- * @param nonce_i initiators nonce
- * @param nonce_r responders nonce
- * @param initiator TRUE if initiator, FALSE otherwise
- * @param child_prf PRF with SK_d key when rekeying, NULL otherwise
- * @param old_prf general purpose PRF of old SA when rekeying
- */
- status_t (*derive_keys)(ike_sa_t *this, proposal_t* proposal, chunk_t secret,
- chunk_t nonce_i, chunk_t nonce_r,
- bool initiator, prf_t *child_prf, prf_t *old_prf);
/**
- * Get the selected IKE proposal string
+ * Get the keying material of this IKE_SA.
*
- * @return string describing the selected IKE proposal
- */
- char* (*get_proposal)(ike_sa_t *this);
-
- /**
- * Set the selected IKE proposal string for status information purposes
- * (the "%P" printf format handler is used)
- *
- * @param proposal string describing the selected IKE proposal
- */
- void (*set_proposal)(ike_sa_t *this, char *proposal);
-
- /**
- * Get a multi purpose prf for the negotiated PRF function.
- *
- * @return pointer to prf_t object
- */
- prf_t *(*get_prf) (ike_sa_t *this);
-
- /**
- * Get the prf-object, which is used to derive keys for child SAs.
- *
- * @return pointer to prf_t object
- */
- prf_t *(*get_child_prf) (ike_sa_t *this);
-
- /**
- * Get the key to build outgoing authentication data.
- *
- * @return pointer to prf_t object
- */
- chunk_t (*get_skp_build) (ike_sa_t *this);
-
- /**
- * Get the key to verify incoming authentication data.
- *
- * @return pointer to prf_t object
+ * @return per IKE_SA keymat instance
*/
- chunk_t (*get_skp_verify) (ike_sa_t *this);
+ keymat_t* (*get_keymat)(ike_sa_t *this);
/**
* Associates a child SA to this IKE SA
@@ -901,6 +863,17 @@ struct ike_sa_t {
void (*add_dns_server) (ike_sa_t *this, host_t *dns);
/**
+ * Set local and remote host addresses to be used for IKE.
+ *
+ * These addresses are communicated via the KMADDRESS field of a MIGRATE
+ * message sent via the NETLINK or PF _KEY kernel socket interface.
+ *
+ * @param local local kmaddress
+ * @param remote remote kmaddress
+ */
+ void (*set_kmaddress) (ike_sa_t *this, host_t *local, host_t *remote);
+
+ /**
* Inherit all attributes of other to this after rekeying.
*
* When rekeying is completed, all CHILD_SAs, the virtual IP and all
diff --git a/src/charon/sa/ike_sa_manager.c b/src/charon/sa/ike_sa_manager.c
index bd7b84c6f..a760409c0 100644
--- a/src/charon/sa/ike_sa_manager.c
+++ b/src/charon/sa/ike_sa_manager.c
@@ -13,10 +13,9 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_sa_manager.c 4234 2008-07-30 14:15:08Z martin $
+ * $Id: ike_sa_manager.c 4579 2008-11-05 11:29:56Z martin $
*/
-#include <pthread.h>
#include <string.h>
#include "ike_sa_manager.h"
@@ -24,6 +23,7 @@
#include <daemon.h>
#include <sa/ike_sa_id.h>
#include <bus/bus.h>
+#include <utils/mutex.h>
#include <utils/linked_list.h>
#include <crypto/hashers/hasher.h>
@@ -42,7 +42,7 @@ struct entry_t {
/**
* Condvar where threads can wait until ike_sa_t object is free for use again.
*/
- pthread_cond_t condvar;
+ condvar_t *condvar;
/**
* Is this ike_sa currently checked out?
@@ -107,6 +107,7 @@ static status_t entry_destroy(entry_t *this)
DESTROY_IF(this->other);
DESTROY_IF(this->my_id);
DESTROY_IF(this->other_id);
+ this->condvar->destroy(this->condvar);
free(this);
return SUCCESS;
}
@@ -119,7 +120,7 @@ static entry_t *entry_create(ike_sa_id_t *ike_sa_id)
entry_t *this = malloc_thing(entry_t);
this->waiting_threads = 0;
- pthread_cond_init(&this->condvar, NULL);
+ this->condvar = condvar_create(CONDVAR_DEFAULT);
/* we set checkout flag when we really give it out */
this->checked_out = FALSE;
@@ -155,7 +156,7 @@ struct private_ike_sa_manager_t {
/**
* Lock for exclusivly accessing the manager.
*/
- pthread_mutex_t mutex;
+ mutex_t *mutex;
/**
* Linked list with entries for the ike_sa_t objects.
@@ -278,9 +279,9 @@ static status_t delete_entry(private_ike_sa_manager_t *this, entry_t *entry)
while (entry->waiting_threads)
{
/* wake up all */
- pthread_cond_broadcast(&(entry->condvar));
+ entry->condvar->broadcast(entry->condvar);
/* they will wake us again when their work is done */
- pthread_cond_wait(&(entry->condvar), &(this->mutex));
+ entry->condvar->wait(entry->condvar, this->mutex);
}
DBG2(DBG_MGR, "found entry by pointer, deleting it");
@@ -310,14 +311,14 @@ static bool wait_for_entry(private_ike_sa_manager_t *this, entry_t *entry)
/* so wait until we can get it for us.
* we register us as waiting. */
entry->waiting_threads++;
- pthread_cond_wait(&(entry->condvar), &(this->mutex));
+ entry->condvar->wait(entry->condvar, this->mutex);
entry->waiting_threads--;
}
/* hm, a deletion request forbids us to get this SA, get next one */
if (entry->driveout_waiting_threads)
{
/* we must signal here, others may be waiting on it, too */
- pthread_cond_signal(&(entry->condvar));
+ entry->condvar->signal(entry->condvar);
return FALSE;
}
return TRUE;
@@ -345,7 +346,7 @@ static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id
DBG2(DBG_MGR, "checkout IKE_SA, %d IKE_SAs in manager",
this->ike_sa_list->get_count(this->ike_sa_list));
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS)
{
if (wait_for_entry(this, entry))
@@ -355,7 +356,7 @@ static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id
ike_sa = entry->ike_sa;
}
}
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
charon->bus->set_sa(charon->bus, ike_sa);
return ike_sa;
}
@@ -378,10 +379,10 @@ static ike_sa_t *checkout_new(private_ike_sa_manager_t* this, bool initiator)
}
entry = entry_create(id);
id->destroy(id);
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
this->ike_sa_list->insert_last(this->ike_sa_list, entry);
entry->checked_out = TRUE;
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
DBG2(DBG_MGR, "created IKE_SA, %d IKE_SAs in manager",
this->ike_sa_list->get_count(this->ike_sa_list));
return entry->ike_sa;
@@ -413,7 +414,7 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
this->hasher->allocate_hash(this->hasher, data, &hash);
chunk_free(&data);
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -422,7 +423,7 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
if (entry->message_id == 0)
{
enumerator->destroy(enumerator);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
chunk_free(&hash);
id->destroy(id);
DBG1(DBG_MGR, "ignoring IKE_SA_INIT, already processing");
@@ -439,7 +440,7 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
}
}
enumerator->destroy(enumerator);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
if (ike_sa == NULL)
{
@@ -450,11 +451,11 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
id->set_responder_spi(id, get_next_spi(this));
entry = entry_create(id);
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
this->ike_sa_list->insert_last(this->ike_sa_list, entry);
entry->checked_out = TRUE;
entry->message_id = message->get_message_id(message);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
entry->init_hash = hash;
ike_sa = entry->ike_sa;
}
@@ -473,7 +474,7 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
return ike_sa;
}
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_entry_by_id(this, id, &entry) == SUCCESS)
{
/* only check out if we are not processing this request */
@@ -496,7 +497,7 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
ike_sa = entry->ike_sa;
}
}
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
id->destroy(id);
charon->bus->set_sa(charon->bus, ike_sa);
return ike_sa;
@@ -521,7 +522,7 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
my_host = host_create_from_dns(ike_cfg->get_my_addr(ike_cfg), 0, 0);
other_host = host_create_from_dns(ike_cfg->get_other_addr(ike_cfg), 0, 0);
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (my_host && other_host && this->reuse_ikesa)
{
@@ -553,8 +554,9 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
/* IKE_SA has no IDs yet, so we can't use it */
continue;
}
- DBG2(DBG_MGR, "candidate IKE_SA for \n\t"
- "%H[%D]...%H[%D]\n\t%H[%D]...%H[%D]",
+ DBG2(DBG_MGR, "candidate IKE_SA for \n"
+ " %H[%D]...%H[%D]\n"
+ " %H[%D]...%H[%D]",
my_host, my_id, other_host, other_id,
found_my_host, found_my_id, found_other_host, found_other_id);
/* compare ID and hosts. Supplied ID may contain wildcards, and IP
@@ -603,7 +605,7 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
new_entry->checked_out = TRUE;
ike_sa = new_entry->ike_sa;
}
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
charon->bus->set_sa(charon->bus, ike_sa);
return ike_sa;
}
@@ -620,7 +622,7 @@ static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id,
ike_sa_t *ike_sa = NULL;
child_sa_t *child_sa;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
while (enumerator->enumerate(enumerator, &entry))
@@ -657,7 +659,7 @@ static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id,
}
}
enumerator->destroy(enumerator);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
charon->bus->set_sa(charon->bus, ike_sa);
return ike_sa;
@@ -675,7 +677,7 @@ static ike_sa_t* checkout_by_name(private_ike_sa_manager_t *this, char *name,
ike_sa_t *ike_sa = NULL;
child_sa_t *child_sa;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
while (enumerator->enumerate(enumerator, &entry))
@@ -712,7 +714,7 @@ static ike_sa_t* checkout_by_name(private_ike_sa_manager_t *this, char *name,
}
}
enumerator->destroy(enumerator);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
charon->bus->set_sa(charon->bus, ike_sa);
return ike_sa;
@@ -732,7 +734,7 @@ static ike_sa_t* checkout_duplicate(private_ike_sa_manager_t *this,
me = ike_sa->get_my_id(ike_sa);
other = ike_sa->get_other_id(ike_sa);
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -755,7 +757,7 @@ static ike_sa_t* checkout_duplicate(private_ike_sa_manager_t *this,
}
}
enumerator->destroy(enumerator);
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
return duplicate;
}
@@ -764,7 +766,7 @@ static ike_sa_t* checkout_duplicate(private_ike_sa_manager_t *this,
*/
static void enumerator_unlock(private_ike_sa_manager_t *this)
{
- pthread_mutex_unlock(&this->mutex);
+ this->mutex->unlock(this->mutex);
}
/**
@@ -786,7 +788,7 @@ static bool enumerator_filter(private_ike_sa_manager_t *this,
*/
static enumerator_t *create_enumerator(private_ike_sa_manager_t* this)
{
- pthread_mutex_lock(&this->mutex);
+ this->mutex->lock(this->mutex);
return enumerator_create_filter(
this->ike_sa_list->create_enumerator(this->ike_sa_list),
(void*)enumerator_filter, this, (void*)enumerator_unlock);
@@ -812,7 +814,7 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
DBG2(DBG_MGR, "checkin IKE_SA");
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
/* look for the entry */
if (get_entry_by_sa(this, ike_sa, &entry) == SUCCESS)
@@ -845,7 +847,7 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
entry->other_id = other_id->clone(other_id);
}
DBG2(DBG_MGR, "check-in of IKE_SA successful.");
- pthread_cond_signal(&(entry->condvar));
+ entry->condvar->signal(entry->condvar);
retval = SUCCESS;
}
else
@@ -857,7 +859,7 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
DBG2(DBG_MGR, "%d IKE_SAs in manager now",
this->ike_sa_list->get_count(this->ike_sa_list));
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
charon->bus->set_sa(charon->bus, NULL);
return retval;
@@ -880,9 +882,8 @@ static status_t checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ik
ike_sa_id = ike_sa->get_id(ike_sa);
DBG2(DBG_MGR, "checkin and destroy IKE_SA");
- charon->bus->set_sa(charon->bus, NULL);
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_entry_by_sa(this, ike_sa, &entry) == SUCCESS)
{
@@ -899,8 +900,9 @@ static status_t checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ik
DBG2(DBG_MGR, "tried to check-in and delete nonexisting IKE_SA");
retval = NOT_FOUND;
}
+ charon->bus->set_sa(charon->bus, NULL);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return retval;
}
@@ -913,7 +915,7 @@ static int get_half_open_count(private_ike_sa_manager_t *this, host_t *ip)
entry_t *entry;
int count = 0;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -937,7 +939,7 @@ static int get_half_open_count(private_ike_sa_manager_t *this, host_t *ip)
}
enumerator->destroy(enumerator);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return count;
}
@@ -950,7 +952,7 @@ static void flush(private_ike_sa_manager_t *this)
enumerator_t *enumerator;
entry_t *entry;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
DBG2(DBG_MGR, "going to destroy IKE_SA manager and all managed IKE_SA's");
/* Step 1: drive out all waiting threads */
DBG2(DBG_MGR, "set driveout flags for all stored IKE_SA's");
@@ -970,9 +972,9 @@ static void flush(private_ike_sa_manager_t *this)
while (entry->waiting_threads)
{
/* wake up all */
- pthread_cond_broadcast(&(entry->condvar));
+ entry->condvar->broadcast(entry->condvar);
/* go sleeping until they are gone */
- pthread_cond_wait(&(entry->condvar), &(this->mutex));
+ entry->condvar->wait(entry->condvar, this->mutex);
}
}
enumerator->destroy(enumerator);
@@ -981,6 +983,7 @@ static void flush(private_ike_sa_manager_t *this)
enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
while (enumerator->enumerate(enumerator, &entry))
{
+ charon->bus->set_sa(charon->bus, entry->ike_sa);
entry->ike_sa->delete(entry->ike_sa);
}
enumerator->destroy(enumerator);
@@ -990,9 +993,11 @@ static void flush(private_ike_sa_manager_t *this)
while (this->ike_sa_list->remove_last(this->ike_sa_list,
(void**)&entry) == SUCCESS)
{
+ charon->bus->set_sa(charon->bus, entry->ike_sa);
entry_destroy(entry);
}
- pthread_mutex_unlock(&(this->mutex));
+ charon->bus->set_sa(charon->bus, NULL);
+ this->mutex->unlock(this->mutex);
}
/**
@@ -1003,7 +1008,7 @@ static void destroy(private_ike_sa_manager_t *this)
this->ike_sa_list->destroy(this->ike_sa_list);
this->rng->destroy(this->rng);
this->hasher->destroy(this->hasher);
-
+ this->mutex->destroy(this->mutex);
free(this);
}
@@ -1046,7 +1051,7 @@ ike_sa_manager_t *ike_sa_manager_create()
return NULL;
}
this->ike_sa_list = linked_list_create();
- pthread_mutex_init(&this->mutex, NULL);
+ this->mutex = mutex_create(MUTEX_DEFAULT);
this->reuse_ikesa = lib->settings->get_bool(lib->settings,
"charon.reuse_ikesa", TRUE);
return &this->public;
diff --git a/src/charon/sa/ike_sa_manager.h b/src/charon/sa/ike_sa_manager.h
index 04b6d96c2..3f0752cc8 100644
--- a/src/charon/sa/ike_sa_manager.h
+++ b/src/charon/sa/ike_sa_manager.h
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_sa_manager.h 3819 2008-04-17 10:46:25Z martin $
+ * $Id: ike_sa_manager.h 4624 2008-11-11 13:11:44Z tobias $
*/
/**
@@ -59,7 +59,7 @@ struct ike_sa_manager_t {
* Create and check out a new IKE_SA.
*
* @param initiator TRUE for initiator, FALSE otherwise
- * @returns created andchecked out IKE_SA
+ * @returns created and checked out IKE_SA
*/
ike_sa_t* (*checkout_new) (ike_sa_manager_t* this, bool initiator);
@@ -67,13 +67,13 @@ struct ike_sa_manager_t {
* Checkout an IKE_SA by a message.
*
* In some situations, it is necessary that the manager knows the
- * message to use for the checkout. This has the folloing reasons:
+ * message to use for the checkout. This has the following reasons:
*
* 1. If the targeted IKE_SA is already processing a message, we do not
* check it out if the message ID is the same.
* 2. If it is an IKE_SA_INIT request, we have to check if it is a
* retransmission. If so, we have to drop the message, we would
- * create another unneded IKE_SA for each retransmitted packet.
+ * create another unneeded IKE_SA for each retransmitted packet.
*
* A call to checkout_by_message() returns a (maybe new created) IKE_SA.
* If processing the message does not make sense (for the reasons above),
diff --git a/src/charon/sa/keymat.c b/src/charon/sa/keymat.c
new file mode 100644
index 000000000..c65bfc3b7
--- /dev/null
+++ b/src/charon/sa/keymat.c
@@ -0,0 +1,568 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+#include "keymat.h"
+
+#include <daemon.h>
+#include <crypto/prf_plus.h>
+
+typedef struct private_keymat_t private_keymat_t;
+
+/**
+ * Private data of an keymat_t object.
+ */
+struct private_keymat_t {
+
+ /**
+ * Public keymat_t interface.
+ */
+ keymat_t public;
+
+ /**
+ * IKE_SA Role, initiator or responder
+ */
+ bool initiator;
+
+ /**
+ * inbound signer (verify)
+ */
+ signer_t *signer_in;
+
+ /**
+ * outbound signer (sign)
+ */
+ signer_t *signer_out;
+
+ /**
+ * inbound crypter (decrypt)
+ */
+ crypter_t *crypter_in;
+
+ /**
+ * outbound crypter (encrypt)
+ */
+ crypter_t *crypter_out;
+
+ /**
+ * General purpose PRF
+ */
+ prf_t *prf;
+
+ /**
+ * Key to derive key material from for CHILD_SAs, rekeying
+ */
+ chunk_t skd;
+
+ /**
+ * Key to build outging authentication data (SKp)
+ */
+ chunk_t skp_build;
+
+ /**
+ * Key to verify incoming authentication data (SKp)
+ */
+ chunk_t skp_verify;
+};
+
+typedef struct keylen_entry_t keylen_entry_t;
+
+/**
+ * Implicit key length for an algorithm
+ */
+struct keylen_entry_t {
+ /** IKEv2 algorithm identifier */
+ int algo;
+ /** key length in bits */
+ int len;
+};
+
+#define END_OF_LIST -1
+
+/**
+ * Keylen for encryption algos
+ */
+keylen_entry_t keylen_enc[] = {
+ {ENCR_DES, 64},
+ {ENCR_3DES, 192},
+ {END_OF_LIST, 0}
+};
+
+/**
+ * Keylen for integrity algos
+ */
+keylen_entry_t keylen_int[] = {
+ {AUTH_HMAC_MD5_96, 128},
+ {AUTH_HMAC_SHA1_96, 160},
+ {AUTH_HMAC_SHA2_256_128, 256},
+ {AUTH_HMAC_SHA2_384_192, 384},
+ {AUTH_HMAC_SHA2_512_256, 512},
+ {AUTH_AES_XCBC_96, 128},
+ {END_OF_LIST, 0}
+};
+
+/**
+ * Lookup key length of an algorithm
+ */
+static int lookup_keylen(keylen_entry_t *list, int algo)
+{
+ while (list->algo != END_OF_LIST)
+ {
+ if (algo == list->algo)
+ {
+ return list->len;
+ }
+ list++;
+ }
+ return 0;
+}
+
+/**
+ * Implementation of keymat_t.create_dh
+ */
+static diffie_hellman_t* create_dh(private_keymat_t *this,
+ diffie_hellman_group_t group)
+{
+ return lib->crypto->create_dh(lib->crypto, group);;
+}
+
+/**
+ * Implementation of keymat_t.derive_keys
+ */
+static bool derive_ike_keys(private_keymat_t *this, proposal_t *proposal,
+ diffie_hellman_t *dh, chunk_t nonce_i,
+ chunk_t nonce_r, ike_sa_id_t *id,
+ private_keymat_t *rekey)
+{
+ chunk_t skeyseed, key, secret, full_nonce, fixed_nonce, prf_plus_seed;
+ chunk_t spi_i, spi_r;
+ crypter_t *crypter_i, *crypter_r;
+ signer_t *signer_i, *signer_r;
+ prf_plus_t *prf_plus;
+ u_int16_t alg, key_size;
+
+ spi_i = chunk_alloca(sizeof(u_int64_t));
+ spi_r = chunk_alloca(sizeof(u_int64_t));
+
+ if (dh->get_shared_secret(dh, &secret) != SUCCESS)
+ {
+ return FALSE;
+ }
+
+ /* Create SAs general purpose PRF first, we may use it here */
+ if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
+ {
+ DBG1(DBG_IKE, "no %N selected",
+ transform_type_names, PSEUDO_RANDOM_FUNCTION);
+ return FALSE;
+ }
+ this->prf = lib->crypto->create_prf(lib->crypto, alg);
+ if (this->prf == NULL)
+ {
+ DBG1(DBG_IKE, "%N %N not supported!",
+ transform_type_names, PSEUDO_RANDOM_FUNCTION,
+ pseudo_random_function_names, alg);
+ return FALSE;
+ }
+ DBG4(DBG_IKE, "shared Diffie Hellman secret %B", &secret);
+ /* full nonce is used as seed for PRF+ ... */
+ full_nonce = chunk_cat("cc", nonce_i, nonce_r);
+ /* but the PRF may need a fixed key which only uses the first bytes of
+ * the nonces. */
+ switch (alg)
+ {
+ case PRF_AES128_XCBC:
+ /* while rfc4434 defines variable keys for AES-XCBC, rfc3664 does
+ * not and therefore fixed key semantics apply to XCBC for key
+ * derivation. */
+ key_size = this->prf->get_key_size(this->prf)/2;
+ nonce_i.len = min(nonce_i.len, key_size);
+ nonce_r.len = min(nonce_r.len, key_size);
+ break;
+ default:
+ /* all other algorithms use variable key length, full nonce */
+ break;
+ }
+ fixed_nonce = chunk_cat("cc", nonce_i, nonce_r);
+ *((u_int64_t*)spi_i.ptr) = id->get_initiator_spi(id);
+ *((u_int64_t*)spi_r.ptr) = id->get_responder_spi(id);
+ prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r);
+
+ /* KEYMAT = prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr)
+ *
+ * if we are rekeying, SKEYSEED is built on another way
+ */
+ if (rekey == NULL) /* not rekeying */
+ {
+ /* SKEYSEED = prf(Ni | Nr, g^ir) */
+ this->prf->set_key(this->prf, fixed_nonce);
+ this->prf->allocate_bytes(this->prf, secret, &skeyseed);
+ this->prf->set_key(this->prf, skeyseed);
+ prf_plus = prf_plus_create(this->prf, prf_plus_seed);
+ }
+ else
+ {
+ /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr)
+ * use OLD SAs PRF functions for both prf_plus and prf */
+ secret = chunk_cat("mc", secret, full_nonce);
+ rekey->prf->set_key(rekey->prf, rekey->skd);
+ rekey->prf->allocate_bytes(rekey->prf, secret, &skeyseed);
+ rekey->prf->set_key(rekey->prf, skeyseed);
+ prf_plus = prf_plus_create(rekey->prf, prf_plus_seed);
+ }
+ DBG4(DBG_IKE, "SKEYSEED %B", &skeyseed);
+
+ chunk_clear(&skeyseed);
+ chunk_clear(&secret);
+ chunk_free(&full_nonce);
+ chunk_free(&fixed_nonce);
+ chunk_clear(&prf_plus_seed);
+
+ /* KEYMAT = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr */
+
+ /* SK_d is used for generating CHILD_SA key mat => store for later use */
+ key_size = this->prf->get_key_size(this->prf);
+ prf_plus->allocate_bytes(prf_plus, key_size, &this->skd);
+ DBG4(DBG_IKE, "Sk_d secret %B", &this->skd);
+
+ /* SK_ai/SK_ar used for integrity protection => signer_in/signer_out */
+ if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL))
+ {
+ DBG1(DBG_IKE, "no %N selected",
+ transform_type_names, INTEGRITY_ALGORITHM);
+ return FALSE;
+ }
+ signer_i = lib->crypto->create_signer(lib->crypto, alg);
+ signer_r = lib->crypto->create_signer(lib->crypto, alg);
+ if (signer_i == NULL || signer_r == NULL)
+ {
+ DBG1(DBG_IKE, "%N %N not supported!",
+ transform_type_names, INTEGRITY_ALGORITHM,
+ integrity_algorithm_names ,alg);
+ prf_plus->destroy(prf_plus);
+ return FALSE;
+ }
+ key_size = signer_i->get_key_size(signer_i);
+
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_ai secret %B", &key);
+ signer_i->set_key(signer_i, key);
+ chunk_clear(&key);
+
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_ar secret %B", &key);
+ signer_r->set_key(signer_r, key);
+ chunk_clear(&key);
+
+ if (this->initiator)
+ {
+ this->signer_in = signer_r;
+ this->signer_out = signer_i;
+ }
+ else
+ {
+ this->signer_in = signer_i;
+ this->signer_out = signer_r;
+ }
+
+ /* SK_ei/SK_er used for encryption => crypter_in/crypter_out */
+ if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &key_size))
+ {
+ DBG1(DBG_IKE, "no %N selected",
+ transform_type_names, ENCRYPTION_ALGORITHM);
+ prf_plus->destroy(prf_plus);
+ return FALSE;
+ }
+ crypter_i = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
+ crypter_r = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
+ if (crypter_i == NULL || crypter_r == NULL)
+ {
+ DBG1(DBG_IKE, "%N %N (key size %d) not supported!",
+ transform_type_names, ENCRYPTION_ALGORITHM,
+ encryption_algorithm_names, alg, key_size);
+ prf_plus->destroy(prf_plus);
+ return FALSE;
+ }
+ key_size = crypter_i->get_key_size(crypter_i);
+
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_ei secret %B", &key);
+ crypter_i->set_key(crypter_i, key);
+ chunk_clear(&key);
+
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_er secret %B", &key);
+ crypter_r->set_key(crypter_r, key);
+ chunk_clear(&key);
+
+ if (this->initiator)
+ {
+ this->crypter_in = crypter_r;
+ this->crypter_out = crypter_i;
+ }
+ else
+ {
+ this->crypter_in = crypter_i;
+ this->crypter_out = crypter_r;
+ }
+
+ /* SK_pi/SK_pr used for authentication => stored for later */
+ key_size = this->prf->get_key_size(this->prf);
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_pi secret %B", &key);
+ if (this->initiator)
+ {
+ this->skp_build = key;
+ }
+ else
+ {
+ this->skp_verify = key;
+ }
+ prf_plus->allocate_bytes(prf_plus, key_size, &key);
+ DBG4(DBG_IKE, "Sk_pr secret %B", &key);
+ if (this->initiator)
+ {
+ this->skp_verify = key;
+ }
+ else
+ {
+ this->skp_build = key;
+ }
+
+ /* all done, prf_plus not needed anymore */
+ prf_plus->destroy(prf_plus);
+
+ return TRUE;
+}
+
+/**
+ * Implementation of keymat_t.derive_child_keys
+ */
+static bool derive_child_keys(private_keymat_t *this,
+ proposal_t *proposal, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r,
+ chunk_t *encr_i, chunk_t *integ_i,
+ chunk_t *encr_r, chunk_t *integ_r)
+{
+ u_int16_t enc_alg, int_alg, enc_size = 0, int_size = 0;
+ chunk_t seed, secret = chunk_empty;
+ prf_plus_t *prf_plus;
+
+ if (dh)
+ {
+ if (dh->get_shared_secret(dh, &secret) != SUCCESS)
+ {
+ return FALSE;
+ }
+ DBG4(DBG_CHD, "DH secret %B", &secret);
+ }
+ seed = chunk_cata("mcc", secret, nonce_i, nonce_r);
+ DBG4(DBG_CHD, "seed %B", &seed);
+
+ if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
+ &enc_alg, &enc_size))
+ {
+ DBG2(DBG_CHD, " using %N for encryption",
+ encryption_algorithm_names, enc_alg);
+
+ if (!enc_size)
+ {
+ enc_size = lookup_keylen(keylen_enc, enc_alg);
+ }
+ if (!enc_size)
+ {
+ DBG1(DBG_CHD, "no keylenth defined for %N",
+ encryption_algorithm_names, enc_alg);
+ return FALSE;
+ }
+ /* to bytes */
+ enc_size /= 8;
+
+ /* CCM/GCM needs additional bytes */
+ switch (enc_alg)
+ {
+ case ENCR_AES_CCM_ICV8:
+ case ENCR_AES_CCM_ICV12:
+ case ENCR_AES_CCM_ICV16:
+ enc_size += 3;
+ break;
+ case ENCR_AES_GCM_ICV8:
+ case ENCR_AES_GCM_ICV12:
+ case ENCR_AES_GCM_ICV16:
+ enc_size += 4;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
+ &int_alg, &int_size))
+ {
+ DBG2(DBG_CHD, " using %N for integrity",
+ integrity_algorithm_names, int_alg);
+
+ if (!int_size)
+ {
+ int_size = lookup_keylen(keylen_int, int_alg);
+ }
+ if (!int_size)
+ {
+ DBG1(DBG_CHD, "no keylenth defined for %N",
+ integrity_algorithm_names, int_alg);
+ return FALSE;
+ }
+ /* to bytes */
+ int_size /= 8;
+ }
+
+ this->prf->set_key(this->prf, this->skd);
+ prf_plus = prf_plus_create(this->prf, seed);
+
+ prf_plus->allocate_bytes(prf_plus, enc_size, encr_i);
+ prf_plus->allocate_bytes(prf_plus, int_size, integ_i);
+ prf_plus->allocate_bytes(prf_plus, enc_size, encr_r);
+ prf_plus->allocate_bytes(prf_plus, int_size, integ_r);
+
+ prf_plus->destroy(prf_plus);
+
+ return TRUE;
+}
+
+/**
+ * Implementation of keymat_t.get_signer
+ */
+static signer_t* get_signer(private_keymat_t *this, bool in)
+{
+ return in ? this->signer_in : this->signer_out;
+}
+
+/**
+ * Implementation of keymat_t.get_crypter
+ */
+static crypter_t* get_crypter(private_keymat_t *this, bool in)
+{
+ return in ? this->crypter_in : this->crypter_out;
+}
+
+/**
+ * Implementation of keymat_t.get_auth_octets
+ */
+static chunk_t get_auth_octets(private_keymat_t *this, bool verify,
+ chunk_t ike_sa_init, chunk_t nonce,
+ identification_t *id)
+{
+ chunk_t chunk, idx, octets;
+ chunk_t skp;
+
+ skp = verify ? this->skp_verify : this->skp_build;
+
+ chunk = chunk_alloca(4);
+ memset(chunk.ptr, 0, chunk.len);
+ chunk.ptr[0] = id->get_type(id);
+ idx = chunk_cata("cc", chunk, id->get_encoding(id));
+
+ DBG3(DBG_IKE, "IDx' %B", &idx);
+ DBG3(DBG_IKE, "SK_p %B", &skp);
+ this->prf->set_key(this->prf, skp);
+ this->prf->allocate_bytes(this->prf, idx, &chunk);
+
+ octets = chunk_cat("ccm", ike_sa_init, nonce, chunk);
+ DBG3(DBG_IKE, "octets = message + nonce + prf(Sk_px, IDx') %B", &octets);
+ return octets;
+}
+
+/**
+ * Key pad for the AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
+ */
+#define IKEV2_KEY_PAD "Key Pad for IKEv2"
+#define IKEV2_KEY_PAD_LENGTH 17
+
+/**
+ * Implementation of keymat_t.get_psk_sig
+ */
+static chunk_t get_psk_sig(private_keymat_t *this, bool verify,
+ chunk_t ike_sa_init, chunk_t nonce, chunk_t secret,
+ identification_t *id)
+{
+ chunk_t key_pad, key, sig, octets;
+
+ if (!secret.len)
+ { /* EAP uses SK_p if no MSK has been established */
+ secret = verify ? this->skp_verify : this->skp_build;
+ }
+ octets = get_auth_octets(this, verify, ike_sa_init, nonce, id);
+ /* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */
+ key_pad = chunk_create(IKEV2_KEY_PAD, IKEV2_KEY_PAD_LENGTH);
+ this->prf->set_key(this->prf, secret);
+ this->prf->allocate_bytes(this->prf, key_pad, &key);
+ this->prf->set_key(this->prf, key);
+ this->prf->allocate_bytes(this->prf, octets, &sig);
+ DBG4(DBG_IKE, "secret %B", &secret);
+ DBG4(DBG_IKE, "prf(secret, keypad) %B", &key);
+ DBG3(DBG_IKE, "AUTH = prf(prf(secret, keypad), octets) %B", &sig);
+ chunk_free(&octets);
+ chunk_free(&key);
+
+ return sig;
+}
+
+/**
+ * Implementation of keymat_t.destroy.
+ */
+static void destroy(private_keymat_t *this)
+{
+ DESTROY_IF(this->signer_in);
+ DESTROY_IF(this->signer_out);
+ DESTROY_IF(this->crypter_in);
+ DESTROY_IF(this->crypter_out);
+ DESTROY_IF(this->prf);
+ chunk_clear(&this->skd);
+ chunk_clear(&this->skp_verify);
+ chunk_clear(&this->skp_build);
+ free(this);
+}
+
+/**
+ * See header
+ */
+keymat_t *keymat_create(bool initiator)
+{
+ private_keymat_t *this = malloc_thing(private_keymat_t);
+
+ this->public.create_dh = (diffie_hellman_t*(*)(keymat_t*, diffie_hellman_group_t group))create_dh;
+ this->public.derive_ike_keys = (bool(*)(keymat_t*, proposal_t *proposal, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id, keymat_t *rekey))derive_ike_keys;
+ this->public.derive_child_keys = (bool(*)(keymat_t*, proposal_t *proposal, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i, chunk_t *encr_r, chunk_t *integ_r))derive_child_keys;
+ this->public.get_signer = (signer_t*(*)(keymat_t*, bool in))get_signer;
+ this->public.get_crypter = (crypter_t*(*)(keymat_t*, bool in))get_crypter;
+ this->public.get_auth_octets = (chunk_t(*)(keymat_t *, bool verify, chunk_t ike_sa_init, chunk_t nonce, identification_t *id))get_auth_octets;
+ this->public.get_psk_sig = (chunk_t(*)(keymat_t*, bool verify, chunk_t ike_sa_init, chunk_t nonce, chunk_t secret, identification_t *id))get_psk_sig;
+ this->public.destroy = (void(*)(keymat_t*))destroy;
+
+ this->initiator = initiator;
+
+ this->signer_in = NULL;
+ this->signer_out = NULL;
+ this->crypter_in = NULL;
+ this->crypter_out = NULL;
+ this->prf = NULL;
+ this->skd = chunk_empty;
+ this->skp_verify = chunk_empty;
+ this->skp_build = chunk_empty;
+
+ return &this->public;
+}
+
diff --git a/src/charon/sa/keymat.h b/src/charon/sa/keymat.h
new file mode 100644
index 000000000..3ca25da9e
--- /dev/null
+++ b/src/charon/sa/keymat.h
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ *
+ * $Id$
+ */
+
+/**
+ * @defgroup keymat keymat
+ * @{ @ingroup sa
+ */
+
+#ifndef KEYMAT_H_
+#define KEYMAT_H_
+
+#include <library.h>
+#include <utils/identification.h>
+#include <crypto/prfs/prf.h>
+#include <crypto/crypters/crypter.h>
+#include <crypto/signers/signer.h>
+#include <config/proposal.h>
+#include <sa/ike_sa_id.h>
+
+typedef struct keymat_t keymat_t;
+
+/**
+ * Derivation an management of sensitive keying material.
+ */
+struct keymat_t {
+
+ /**
+ * Create a diffie hellman object for key agreement.
+ *
+ * The diffie hellman is either for IKE negotiation/rekeying or
+ * CHILD_SA rekeying (using PFS). The resulting DH object must be passed
+ * to derive_keys or to derive_child_keys and destroyed after use
+ *
+ * @param group diffie hellman group
+ * @return DH object, NULL if group not supported
+ */
+ diffie_hellman_t* (*create_dh)(keymat_t *this, diffie_hellman_group_t group);
+
+ /**
+ * Derive keys for the IKE_SA.
+ *
+ * These keys are not handed out, but are used by the associated signers,
+ * crypters and authentication functions.
+ *
+ * @param proposal selected algorithms
+ * @param dh diffie hellman key allocated by create_dh()
+ * @param nonce_i initiators nonce value
+ * @param nonce_r responders nonce value
+ * @param id IKE_SA identifier
+ * @param rekey keymat of old SA if we are rekeying
+ * @return TRUE on success
+ */
+ bool (*derive_ike_keys)(keymat_t *this, proposal_t *proposal,
+ diffie_hellman_t *dh, chunk_t nonce_i,
+ chunk_t nonce_r, ike_sa_id_t *id, keymat_t *rekey);
+ /**
+ * Derive keys for a CHILD_SA.
+ *
+ * The keys for the CHILD_SA are allocated in the integ and encr chunks.
+ * An implementation might hand out encrypted keys only, which are
+ * decrypted in the kernel before use.
+ * If no PFS is used for the CHILD_SA, dh can be NULL.
+ *
+ * @param proposal selected algorithms
+ * @param dh diffie hellman key allocated by create_dh(), or NULL
+ * @param nonce_i initiators nonce value
+ * @param nonce_r responders nonce value
+ * @param encr_i chunk to write initiators encryption key to
+ * @param integ_i chunk to write initiators integrity key to
+ * @param encr_r chunk to write responders encryption key to
+ * @param integ_r chunk to write responders integrity key to
+ * @return TRUE on success
+ */
+ bool (*derive_child_keys)(keymat_t *this,
+ proposal_t *proposal, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r,
+ chunk_t *encr_i, chunk_t *integ_i,
+ chunk_t *encr_r, chunk_t *integ_r);
+ /**
+ * Get a signer to sign/verify IKE messages.
+ *
+ * @param in TRUE for inbound (verify), FALSE for outbound (sign)
+ * @return signer
+ */
+ signer_t* (*get_signer)(keymat_t *this, bool in);
+
+ /*
+ * Get a crypter to en-/decrypt IKE messages.
+ *
+ * @param in TRUE for inbound (decrypt), FALSE for outbound (encrypt)
+ * @return crypter
+ */
+ crypter_t* (*get_crypter)(keymat_t *this, bool in);
+
+ /**
+ * Generate octets to use for authentication procedure (RFC4306 2.15).
+ *
+ * This method creates the plain octets and is usually signed by a private
+ * key. PSK and EAP authentication include a secret into the data, use
+ * the get_psk_sig() method instead.
+ *
+ * @param verify TRUE to create for verfification, FALSE to sign
+ * @param ike_sa_init encoded ike_sa_init message
+ * @param nonce nonce value
+ * @param id identity
+ * @return authentication octets
+ */
+ chunk_t (*get_auth_octets)(keymat_t *this, bool verify, chunk_t ike_sa_init,
+ chunk_t nonce, identification_t *id);
+ /**
+ * Build the shared secret signature used for PSK and EAP authentication.
+ *
+ * This method wraps the get_auth_octets() method and additionally
+ * includes the secret into the signature. If no secret is given, SK_p is
+ * used as secret (used for EAP methods without MSK).
+ *
+ * @param verify TRUE to create for verfification, FALSE to sign
+ * @param ike_sa_init encoded ike_sa_init message
+ * @param nonce nonce value
+ * @param secret optional secret to include into signature
+ * @param id identity
+ * @return signature octets
+ */
+ chunk_t (*get_psk_sig)(keymat_t *this, bool verify, chunk_t ike_sa_init,
+ chunk_t nonce, chunk_t secret, identification_t *id);
+ /**
+ * Destroy a keymat_t.
+ */
+ void (*destroy)(keymat_t *this);
+};
+
+/**
+ * Create a keymat instance.
+ *
+ * @param initiator TRUE if we are the initiator
+ * @return keymat instance
+ */
+keymat_t *keymat_create(bool initiator);
+
+#endif /* KEYMAT_ @}*/
diff --git a/src/charon/sa/mediation_manager.c b/src/charon/sa/mediation_manager.c
index d15f4c100..b508c48c3 100644
--- a/src/charon/sa/mediation_manager.c
+++ b/src/charon/sa/mediation_manager.c
@@ -12,13 +12,13 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: mediation_manager.c 3773 2008-04-07 09:36:52Z tobias $
+ * $Id: mediation_manager.c 4579 2008-11-05 11:29:56Z martin $
*/
#include "mediation_manager.h"
-#include <pthread.h>
#include <daemon.h>
+#include <utils/mutex.h>
#include <utils/linked_list.h>
#include <processing/jobs/mediation_job.h>
@@ -80,7 +80,7 @@ struct private_mediation_manager_t {
/**
* Lock for exclusivly accessing the manager.
*/
- pthread_mutex_t mutex;
+ mutex_t *mutex;
/**
* Linked list with state entries.
@@ -182,7 +182,7 @@ static void remove_sa(private_mediation_manager_t *this, ike_sa_id_t *ike_sa_id)
iterator_t *iterator;
peer_t *peer;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
iterator = this->peers->create_iterator(this->peers, TRUE);
while (iterator->iterate(iterator, (void**)&peer))
@@ -199,7 +199,7 @@ static void remove_sa(private_mediation_manager_t *this, ike_sa_id_t *ike_sa_id)
}
iterator->destroy(iterator);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
}
/**
@@ -211,7 +211,7 @@ static void update_sa_id(private_mediation_manager_t *this, identification_t *pe
peer_t *peer;
bool found = FALSE;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
iterator = this->peers->create_iterator(this->peers, TRUE);
while (iterator->iterate(iterator, (void**)&peer))
@@ -244,7 +244,7 @@ static void update_sa_id(private_mediation_manager_t *this, identification_t *pe
requester->destroy(requester);
}
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
}
/**
@@ -256,17 +256,17 @@ static ike_sa_id_t *check(private_mediation_manager_t *this,
peer_t *peer;
ike_sa_id_t *ike_sa_id;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_peer_by_id(this, peer_id, &peer) != SUCCESS)
{
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return NULL;
}
ike_sa_id = peer->ike_sa_id;
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return ike_sa_id;
}
@@ -280,7 +280,7 @@ static ike_sa_id_t *check_and_register(private_mediation_manager_t *this,
peer_t *peer;
ike_sa_id_t *ike_sa_id;
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
if (get_peer_by_id(this, peer_id, &peer) != SUCCESS)
{
@@ -294,13 +294,13 @@ static ike_sa_id_t *check_and_register(private_mediation_manager_t *this,
/* the peer is not online */
DBG2(DBG_IKE, "requested peer '%D' is offline, registering peer '%D'", peer_id, requester);
register_peer(peer, requester);
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return NULL;
}
ike_sa_id = peer->ike_sa_id;
- pthread_mutex_unlock(&(this->mutex));
+ this->mutex->unlock(this->mutex);
return ike_sa_id;
}
@@ -310,12 +310,12 @@ static ike_sa_id_t *check_and_register(private_mediation_manager_t *this,
*/
static void destroy(private_mediation_manager_t *this)
{
- pthread_mutex_lock(&(this->mutex));
+ this->mutex->lock(this->mutex);
this->peers->destroy_function(this->peers, (void*)peer_destroy);
- pthread_mutex_unlock(&(this->mutex));
- pthread_mutex_destroy(&(this->mutex));
+ this->mutex->unlock(this->mutex);
+ this->mutex->destroy(this->mutex);
free(this);
}
@@ -333,7 +333,7 @@ mediation_manager_t *mediation_manager_create()
this->public.check_and_register = (ike_sa_id_t*(*)(mediation_manager_t*,identification_t*,identification_t*))check_and_register;
this->peers = linked_list_create();
- pthread_mutex_init(&(this->mutex), NULL);
+ this->mutex = mutex_create(MUTEX_DEFAULT);
return (mediation_manager_t*)this;
}
diff --git a/src/charon/sa/task_manager.c b/src/charon/sa/task_manager.c
index 25089477b..0630647c9 100644
--- a/src/charon/sa/task_manager.c
+++ b/src/charon/sa/task_manager.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: task_manager.c 4320 2008-09-02 14:02:40Z martin $
+ * $Id: task_manager.c 4484 2008-10-27 11:13:33Z martin $
*/
#include "task_manager.h"
@@ -145,44 +145,15 @@ struct private_task_manager_t {
*/
static void flush(private_task_manager_t *this)
{
- task_t *task;
-
this->queued_tasks->destroy_offset(this->queued_tasks,
offsetof(task_t, destroy));
this->passive_tasks->destroy_offset(this->passive_tasks,
offsetof(task_t, destroy));
-
- /* emmit outstanding signals for tasks */
- while (this->active_tasks->remove_last(this->active_tasks,
- (void**)&task) == SUCCESS)
- {
- switch (task->get_type(task))
- {
- case IKE_AUTH:
- SIG_IKE(UP_FAILED, "establishing IKE_SA failed");
- break;
- case IKE_DELETE:
- SIG_IKE(DOWN_FAILED, "IKE_SA deleted");
- break;
- case IKE_REKEY:
- SIG_IKE(REKEY_FAILED, "rekeying IKE_SA failed");
- break;
- case CHILD_CREATE:
- SIG_CHD(UP_FAILED, NULL, "establishing CHILD_SA failed");
- break;
- case CHILD_DELETE:
- SIG_CHD(DOWN_FAILED, NULL, "deleting CHILD_SA failed");
- break;
- case CHILD_REKEY:
- SIG_IKE(REKEY_FAILED, "rekeying CHILD_SA failed");
- break;
- default:
- break;
- }
- task->destroy(task);
- }
+ this->active_tasks->destroy_offset(this->active_tasks,
+ offsetof(task_t, destroy));
this->queued_tasks = linked_list_create();
this->passive_tasks = linked_list_create();
+ this->active_tasks = linked_list_create();
}
/**
@@ -648,6 +619,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
DESTROY_IF(this->responding.packet);
status = this->ike_sa->generate_message(this->ike_sa, message,
&this->responding.packet);
+ charon->bus->message(charon->bus, message, FALSE);
message->destroy(message);
if (status != SUCCESS)
{
@@ -867,6 +839,7 @@ static status_t process_message(private_task_manager_t *this, message_t *msg)
{
if (mid == this->responding.mid)
{
+ charon->bus->message(charon->bus, msg, TRUE);
if (process_request(this, msg) != SUCCESS)
{
flush(this);
diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c
index bddca621b..767ceef55 100644
--- a/src/charon/sa/tasks/child_create.c
+++ b/src/charon/sa/tasks/child_create.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 Tobias Brunner
- * Copyright (C) 2005-2007 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: child_create.c 4358 2008-09-25 13:56:23Z tobias $
+ * $Id: child_create.c 4618 2008-11-11 09:22:00Z tobias $
*/
#include "child_create.h"
@@ -97,6 +97,11 @@ struct private_child_create_t {
diffie_hellman_group_t dh_group;
/**
+ * IKE_SAs keymat
+ */
+ keymat_t *keymat;
+
+ /**
* mode the new CHILD_SA uses (transport/tunnel/beet)
*/
ipsec_mode_t mode;
@@ -191,38 +196,22 @@ static bool ts_list_is_host(linked_list_t *list, host_t *host)
*/
static status_t select_and_install(private_child_create_t *this, bool no_dh)
{
- prf_plus_t *prf_plus;
status_t status;
- chunk_t nonce_i, nonce_r, secret, seed;
+ chunk_t nonce_i, nonce_r, encr_i, integ_i, encr_r, integ_r;
linked_list_t *my_ts, *other_ts;
host_t *me, *other, *other_vip, *my_vip;
if (this->proposals == NULL)
{
- SIG_CHD(UP_FAILED, this->child_sa, "SA payload missing in message");
+ DBG1(DBG_IKE, "SA payload missing in message");
return FAILED;
}
if (this->tsi == NULL || this->tsr == NULL)
{
- SIG_CHD(UP_FAILED, this->child_sa, "TS payloads missing in message");
+ DBG1(DBG_IKE, "TS payloads missing in message");
return NOT_FOUND;
}
- if (this->initiator)
- {
- nonce_i = this->my_nonce;
- nonce_r = this->other_nonce;
- my_ts = this->tsi;
- other_ts = this->tsr;
- }
- else
- {
- nonce_r = this->my_nonce;
- nonce_i = this->other_nonce;
- my_ts = this->tsr;
- other_ts = this->tsi;
- }
-
me = this->ike_sa->get_my_host(this->ike_sa);
other = this->ike_sa->get_other_host(this->ike_sa);
my_vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
@@ -232,7 +221,7 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
no_dh);
if (this->proposal == NULL)
{
- SIG_CHD(UP_FAILED, this->child_sa, "no acceptable proposal found");
+ DBG1(DBG_IKE, "no acceptable proposal found");
return FAILED;
}
@@ -243,15 +232,15 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
&group, NULL))
{
- SIG_CHD(UP_FAILED, this->child_sa, "DH group %N inacceptable, "
- "requesting %N", diffie_hellman_group_names, this->dh_group,
- diffie_hellman_group_names, group);
+ DBG1(DBG_IKE, "DH group %N inacceptable, requesting %N",
+ diffie_hellman_group_names, this->dh_group,
+ diffie_hellman_group_names, group);
this->dh_group = group;
return INVALID_ARG;
}
else
{
- SIG_CHD(UP_FAILED, this->child_sa, "no acceptable proposal found");
+ DBG1(DBG_IKE, "no acceptable proposal found");
return FAILED;
}
}
@@ -260,16 +249,25 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
{
my_vip = me;
}
- else if (this->initiator)
- {
- /* to setup firewall rules correctly, CHILD_SA needs the virtual IP */
- this->child_sa->set_virtual_ip(this->child_sa, my_vip);
- }
if (other_vip == NULL)
{
other_vip = other;
}
+ if (this->initiator)
+ {
+ nonce_i = this->my_nonce;
+ nonce_r = this->other_nonce;
+ my_ts = this->tsi;
+ other_ts = this->tsr;
+ }
+ else
+ {
+ nonce_r = this->my_nonce;
+ nonce_i = this->other_nonce;
+ my_ts = this->tsr;
+ other_ts = this->tsi;
+ }
my_ts = this->config->get_traffic_selectors(this->config, TRUE, my_ts,
my_vip);
other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts,
@@ -279,7 +277,7 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
{
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
- SIG_CHD(UP_FAILED, this->child_sa, "no acceptable traffic selectors found");
+ DBG1(DBG_IKE, "no acceptable traffic selectors found");
return NOT_FOUND;
}
@@ -302,16 +300,18 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
switch (this->mode)
{
case MODE_TRANSPORT:
- if (!ts_list_is_host(this->tsi, other) ||
- !ts_list_is_host(this->tsr, me))
+ if (!this->config->use_proxy_mode(this->config) &&
+ (!ts_list_is_host(this->tsi, other) ||
+ !ts_list_is_host(this->tsr, me))
+ )
{
this->mode = MODE_TUNNEL;
- DBG1(DBG_IKE, "not using tranport mode, not host-to-host");
+ DBG1(DBG_IKE, "not using transport mode, not host-to-host");
}
else if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
{
this->mode = MODE_TUNNEL;
- DBG1(DBG_IKE, "not using tranport mode, connection NATed");
+ DBG1(DBG_IKE, "not using transport mode, connection NATed");
}
break;
case MODE_BEET:
@@ -327,55 +327,51 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
}
}
- if (this->dh)
+ this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
+
+ if (this->ipcomp != IPCOMP_NONE)
{
- if (this->dh->get_shared_secret(this->dh, &secret) != SUCCESS)
- {
- SIG_CHD(UP_FAILED, this->child_sa, "DH exchange incomplete");
- return FAILED;
- }
- DBG3(DBG_IKE, "DH secret %B", &secret);
- seed = chunk_cata("mcc", secret, nonce_i, nonce_r);
+ this->child_sa->activate_ipcomp(this->child_sa, this->ipcomp,
+ this->other_cpi);
}
- else
+
+ status = FAILED;
+ if (this->keymat->derive_child_keys(this->keymat, this->proposal,
+ this->dh, nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
{
- seed = chunk_cata("cc", nonce_i, nonce_r);
+ if (this->initiator)
+ {
+ status = this->child_sa->update(this->child_sa, this->proposal,
+ this->mode, integ_r, integ_i, encr_r, encr_i);
+ }
+ else
+ {
+ status = this->child_sa->add(this->child_sa, this->proposal,
+ this->mode, integ_i, integ_r, encr_i, encr_r);
+ }
}
+ chunk_clear(&integ_i);
+ chunk_clear(&integ_r);
+ chunk_clear(&encr_i);
+ chunk_clear(&encr_r);
- if (this->ipcomp != IPCOMP_NONE)
+ if (status != SUCCESS)
{
- this->child_sa->activate_ipcomp(this->child_sa, this->ipcomp,
- this->other_cpi);
+ DBG1(DBG_IKE, "unable to install IPsec SA (SAD) in kernel");
+ return FAILED;
}
status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts,
this->mode, this->proposal->get_protocol(this->proposal));
if (status != SUCCESS)
{
- SIG_CHD(UP_FAILED, this->child_sa,
- "unable to install IPsec policies (SPD) in kernel");
+ DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
return NOT_FOUND;
}
- prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
- if (this->initiator)
- {
- status = this->child_sa->update(this->child_sa, this->proposal,
- this->mode, prf_plus);
- }
- else
- {
- status = this->child_sa->add(this->child_sa, this->proposal,
- this->mode, prf_plus);
- }
- prf_plus->destroy(prf_plus);
+ charon->bus->child_keys(charon->bus, this->child_sa, this->dh,
+ nonce_i, nonce_r);
- if (status != SUCCESS)
- {
- SIG_CHD(UP_FAILED, this->child_sa,
- "unable to install IPsec SA (SAD) in kernel");
- return FAILED;
- }
/* add to IKE_SA, and remove from task */
this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
@@ -499,7 +495,7 @@ static void process_payloads(private_child_create_t *this, message_t *message)
if (!this->initiator)
{
this->dh_group = ke_payload->get_dh_group_number(ke_payload);
- this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
+ this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
}
if (this->dh)
{
@@ -592,13 +588,13 @@ static status_t build_i(private_child_create_t *this, message_t *message)
if (this->reqid)
{
- SIG_CHD(UP_START, NULL, "establishing CHILD_SA %s{%d}",
- this->config->get_name(this->config), this->reqid);
+ DBG0(DBG_IKE, "establishing CHILD_SA %s{%d}",
+ this->config->get_name(this->config), this->reqid);
}
else
{
- SIG_CHD(UP_START, NULL, "establishing CHILD_SA %s",
- this->config->get_name(this->config));
+ DBG0(DBG_IKE, "establishing CHILD_SA %s",
+ this->config->get_name(this->config));
}
/* reuse virtual IP if we already have one */
@@ -641,23 +637,19 @@ static status_t build_i(private_child_create_t *this, message_t *message)
this->dh_group == MODP_NONE);
this->mode = this->config->get_mode(this->config);
- this->child_sa = child_sa_create(
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid,
+ this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
if (this->child_sa->alloc(this->child_sa, this->proposals) != SUCCESS)
{
- SIG_CHD(UP_FAILED, this->child_sa,
- "unable to allocate SPIs from kernel");
+ DBG1(DBG_IKE, "unable to allocate SPIs from kernel");
return FAILED;
}
if (this->dh_group != MODP_NONE)
{
- this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
+ this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
}
if (this->config->use_ipcomp(this->config)) {
@@ -679,7 +671,7 @@ static status_t build_i(private_child_create_t *this, message_t *message)
}
/**
- * Implementation of task_t.process for initiator
+ * Implementation of task_t.process for responder
*/
static status_t process_r(private_child_create_t *this, message_t *message)
{
@@ -785,16 +777,15 @@ static status_t build_r(private_child_create_t *this, message_t *message)
if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
{
- SIG_CHD(UP_FAILED, NULL,
- "unable to create CHILD_SA while rekeying IKE_SA");
+ DBG1(DBG_IKE, "unable to create CHILD_SA while rekeying IKE_SA");
message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty);
return SUCCESS;
}
if (this->config == NULL)
{
- SIG_CHD(UP_FAILED, NULL, "traffic selectors %#R=== %#R inacceptable",
- this->tsr, this->tsi);
+ DBG1(DBG_IKE, "traffic selectors %#R=== %#R inacceptable",
+ this->tsr, this->tsi);
message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
handle_child_sa_failure(this, message);
return SUCCESS;
@@ -813,8 +804,8 @@ static status_t build_r(private_child_create_t *this, message_t *message)
case INTERNAL_ADDRESS_FAILURE:
case FAILED_CP_REQUIRED:
{
- SIG_CHD(UP_FAILED, NULL, "configuration payload negotation "
- "failed, no CHILD_SA built");
+ DBG1(DBG_IKE,"configuration payload negotation "
+ "failed, no CHILD_SA built");
iterator->destroy(iterator);
handle_child_sa_failure(this, message);
return SUCCESS;
@@ -826,11 +817,8 @@ static status_t build_r(private_child_create_t *this, message_t *message)
}
iterator->destroy(iterator);
- this->child_sa = child_sa_create(
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid,
+ this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
if (this->config->use_ipcomp(this->config) &&
@@ -870,14 +858,14 @@ static status_t build_r(private_child_create_t *this, message_t *message)
build_payloads(this, message);
- SIG_CHD(UP_SUCCESS, this->child_sa, "CHILD_SA %s{%d} established "
- "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
- this->child_sa->get_name(this->child_sa),
- this->child_sa->get_reqid(this->child_sa),
- ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
- ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
- this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
- this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
+ DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
+ "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
+ this->child_sa->get_name(this->child_sa),
+ this->child_sa->get_reqid(this->child_sa),
+ ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
+ ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
+ this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
+ this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
return SUCCESS;
}
@@ -929,8 +917,8 @@ static status_t process_i(private_child_create_t *this, message_t *message)
case TS_UNACCEPTABLE:
case INVALID_SELECTORS:
{
- SIG_CHD(UP_FAILED, this->child_sa, "received %N notify, "
- "no CHILD_SA built", notify_type_names, type);
+ DBG1(DBG_IKE, "received %N notify, no CHILD_SA built",
+ notify_type_names, type);
iterator->destroy(iterator);
handle_child_sa_failure(this, message);
/* an error in CHILD_SA creation is not critical */
@@ -963,35 +951,35 @@ static status_t process_i(private_child_create_t *this, message_t *message)
if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE)
{
- SIG_CHD(UP_FAILED, this->child_sa, "received an IPCOMP_SUPPORTED notify"
- " but we did not send one previously, no CHILD_SA built");
+ DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify without requesting"
+ " one, no CHILD_SA built");
handle_child_sa_failure(this, message);
return SUCCESS;
}
else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE)
{
DBG1(DBG_IKE, "peer didn't accept our proposed IPComp transforms, "
- "IPComp is disabled");
+ "IPComp is disabled");
this->ipcomp = IPCOMP_NONE;
}
else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received)
{
- SIG_CHD(UP_FAILED, this->child_sa, "received an IPCOMP_SUPPORTED notify"
- " for a transform we did not propose, no CHILD_SA built");
+ DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify we didn't propose, "
+ "no CHILD_SA built");
handle_child_sa_failure(this, message);
return SUCCESS;
}
if (select_and_install(this, no_dh) == SUCCESS)
{
- SIG_CHD(UP_SUCCESS, this->child_sa, "CHILD_SA %s{%d} established "
- "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
- this->child_sa->get_name(this->child_sa),
- this->child_sa->get_reqid(this->child_sa),
- ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
- ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
- this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
- this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
+ DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
+ "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
+ this->child_sa->get_name(this->child_sa),
+ this->child_sa->get_reqid(this->child_sa),
+ ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
+ ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
+ this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
+ this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
}
else
{
@@ -1144,6 +1132,7 @@ child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config)
this->tsr = NULL;
this->dh = NULL;
this->dh_group = MODP_NONE;
+ this->keymat = ike_sa->get_keymat(ike_sa);
this->child_sa = NULL;
this->mode = MODE_TUNNEL;
this->ipcomp = IPCOMP_NONE;
diff --git a/src/charon/sa/tasks/child_delete.c b/src/charon/sa/tasks/child_delete.c
index a3c74dc90..cab1d63f0 100644
--- a/src/charon/sa/tasks/child_delete.c
+++ b/src/charon/sa/tasks/child_delete.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: child_delete.c 4366 2008-10-03 16:01:14Z martin $
+ * $Id: child_delete.c 4434 2008-10-14 08:52:13Z martin $
*/
#include "child_delete.h"
@@ -222,14 +222,13 @@ static void log_children(private_child_delete_t *this)
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
{
- SIG_CHD(DOWN_START, child_sa, "closing CHILD_SA %s{%d} "
- "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
- child_sa->get_name(child_sa),
- child_sa->get_reqid(child_sa),
- ntohl(child_sa->get_spi(child_sa, TRUE)),
- ntohl(child_sa->get_spi(child_sa, FALSE)),
- child_sa->get_traffic_selectors(child_sa, TRUE),
- child_sa->get_traffic_selectors(child_sa, FALSE));
+ DBG0(DBG_IKE, "closing CHILD_SA %s{%d} "
+ "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
+ child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
+ ntohl(child_sa->get_spi(child_sa, TRUE)),
+ ntohl(child_sa->get_spi(child_sa, FALSE)),
+ child_sa->get_traffic_selectors(child_sa, TRUE),
+ child_sa->get_traffic_selectors(child_sa, FALSE));
}
iterator->destroy(iterator);
}
@@ -254,7 +253,7 @@ static status_t process_i(private_child_delete_t *this, message_t *message)
this->child_sas = linked_list_create();
process_payloads(this, message);
- SIG_CHD(DOWN_SUCCESS, NULL, "CHILD_SA closed");
+ DBG1(DBG_IKE, "CHILD_SA closed");
return destroy_and_reestablish(this);
}
@@ -278,7 +277,7 @@ static status_t build_r(private_child_delete_t *this, message_t *message)
{
build_payloads(this, message);
}
- SIG_CHD(DOWN_SUCCESS, NULL, "CHILD_SA closed");
+ DBG1(DBG_IKE, "CHILD_SA closed");
return destroy_and_reestablish(this);
}
diff --git a/src/charon/sa/tasks/child_rekey.c b/src/charon/sa/tasks/child_rekey.c
index 3953951a3..e50ad33be 100644
--- a/src/charon/sa/tasks/child_rekey.c
+++ b/src/charon/sa/tasks/child_rekey.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: child_rekey.c 3589 2008-03-13 14:14:44Z martin $
+ * $Id: child_rekey.c 4659 2008-11-14 14:05:47Z martin $
*/
#include "child_rekey.h"
@@ -23,6 +23,7 @@
#include <sa/tasks/child_create.h>
#include <sa/tasks/child_delete.h>
#include <processing/jobs/rekey_child_sa_job.h>
+#include <processing/jobs/rekey_ike_sa_job.h>
typedef struct private_child_rekey_t private_child_rekey_t;
@@ -177,6 +178,31 @@ static status_t process_i(private_child_rekey_t *this, message_t *message)
protocol_id_t protocol;
u_int32_t spi;
child_sa_t *to_delete;
+ iterator_t *iterator;
+ payload_t *payload;
+
+ /* handle NO_ADDITIONAL_SAS notify */
+ iterator = message->get_payload_iterator(message);
+ while (iterator->iterate(iterator, (void**)&payload))
+ {
+ if (payload->get_type(payload) == NOTIFY)
+ {
+ notify_payload_t *notify = (notify_payload_t*)payload;
+
+ if (notify->get_notify_type(notify) == NO_ADDITIONAL_SAS)
+ {
+ DBG1(DBG_IKE, "peer seems to not support CHILD_SA rekeying, "
+ "starting reauthentication");
+ this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
+ charon->processor->queue_job(charon->processor,
+ (job_t*)rekey_ike_sa_job_create(
+ this->ike_sa->get_id(this->ike_sa), TRUE));
+ iterator->destroy(iterator);
+ return SUCCESS;
+ }
+ }
+ }
+ iterator->destroy(iterator);
if (this->child_create->task.process(&this->child_create->task, message) == NEED_MORE)
{
diff --git a/src/charon/sa/tasks/ike_auth.c b/src/charon/sa/tasks/ike_auth.c
index 51f37f1b0..5c3f33cbd 100644
--- a/src/charon/sa/tasks/ike_auth.c
+++ b/src/charon/sa/tasks/ike_auth.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details
*
- * $Id: ike_auth.c 4276 2008-08-22 10:44:51Z martin $
+ * $Id: ike_auth.c 4463 2008-10-20 11:38:16Z martin $
*/
#include "ike_auth.h"
@@ -146,6 +146,8 @@ static bool check_uniqueness(private_ike_auth_t *this)
charon->ike_sa_manager->checkin(charon->ike_sa_manager, duplicate);
}
}
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
return cancel;
}
@@ -201,15 +203,15 @@ static status_t build_auth(private_ike_auth_t *this, message_t *message)
config = this->ike_sa->get_peer_cfg(this->ike_sa);
if (!config)
{
- SIG_IKE(UP_FAILED, "unable to authenticate, no peer config found");
+ DBG1(DBG_IKE, "unable to authenticate, no peer config found");
return FAILED;
}
auth = authenticator_create_from_class(this->ike_sa, get_auth_class(config));
if (auth == NULL)
{
- SIG_IKE(UP_FAILED, "configured authentication class %N not supported",
- auth_class_names, get_auth_class(config));
+ DBG1(DBG_IKE, "configured authentication class %N not supported",
+ auth_class_names, get_auth_class(config));
return FAILED;
}
@@ -218,7 +220,7 @@ static status_t build_auth(private_ike_auth_t *this, message_t *message)
auth->destroy(auth);
if (status != SUCCESS)
{
- SIG_IKE(UP_FAILED, "generating authentication data failed");
+ DBG1(DBG_IKE, "generating authentication data failed");
return FAILED;
}
message->add_payload(message, (payload_t*)auth_payload);
@@ -243,7 +245,7 @@ static status_t build_id(private_ike_auth_t *this, message_t *message)
me = config->get_my_id(config);
if (me->contains_wildcards(me))
{
- SIG_IKE(UP_FAILED, "negotiation of own ID failed");
+ DBG1(DBG_IKE, "negotiation of own ID failed");
return FAILED;
}
this->ike_sa->set_my_id(this->ike_sa, me->clone(me));
@@ -284,8 +286,8 @@ static status_t process_auth(private_ike_auth_t *this, message_t *message)
auth_payload->get_auth_method(auth_payload));
if (auth == NULL)
{
- SIG_IKE(UP_FAILED, "authentication method %N used by '%D' not "
- "supported", auth_method_names, auth_method,
+ DBG1(DBG_IKE, "authentication method %N used by '%D' not supported",
+ auth_method_names, auth_method,
this->ike_sa->get_other_id(this->ike_sa));
return NOT_SUPPORTED;
}
@@ -294,7 +296,7 @@ static status_t process_auth(private_ike_auth_t *this, message_t *message)
auth->destroy(auth);
if (status != SUCCESS)
{
- SIG_IKE(UP_FAILED, "authentication of '%D' with %N failed",
+ DBG0(DBG_IKE, "authentication of '%D' with %N failed",
this->ike_sa->get_other_id(this->ike_sa),
auth_method_names, auth_method);
return FAILED;
@@ -315,7 +317,7 @@ static status_t process_id(private_ike_auth_t *this, message_t *message)
if ((this->initiator && idr == NULL) || (!this->initiator && idi == NULL))
{
- SIG_IKE(UP_FAILED, "ID payload missing in message");
+ DBG1(DBG_IKE, "ID payload missing in message");
return FAILED;
}
@@ -325,7 +327,7 @@ static status_t process_id(private_ike_auth_t *this, message_t *message)
req = this->ike_sa->get_other_id(this->ike_sa);
if (!id->matches(id, req))
{
- SIG_IKE(UP_FAILED, "peer ID '%D' unacceptable, '%D' required", id, req);
+ DBG0(DBG_IKE, "peer ID '%D' unacceptable, '%D' required", id, req);
id->destroy(id);
return FAILED;
}
@@ -402,7 +404,7 @@ static status_t build_auth_eap(private_ike_auth_t *this, message_t *message)
if (auth->build(auth, this->my_packet->get_data(this->my_packet),
this->other_nonce, &auth_payload) != SUCCESS)
{
- SIG_IKE(UP_FAILED, "generating authentication data failed");
+ DBG1(DBG_IKE, "generating authentication data failed");
if (!this->initiator)
{
message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
@@ -413,13 +415,13 @@ static status_t build_auth_eap(private_ike_auth_t *this, message_t *message)
if (!this->initiator)
{
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- SIG_IKE(UP_SUCCESS, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
- this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_unique_id(this->ike_sa),
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
+ DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
return SUCCESS;
}
return NEED_MORE;
@@ -448,7 +450,7 @@ static status_t process_auth_eap(private_ike_auth_t *this, message_t *message)
if (!this->peer_authenticated)
{
- SIG_IKE(UP_FAILED, "authentication of '%D' with %N failed",
+ DBG0(DBG_IKE, "authentication of '%D' with %N failed",
this->ike_sa->get_other_id(this->ike_sa),
auth_class_names, AUTH_CLASS_EAP);
if (this->initiator)
@@ -460,13 +462,13 @@ static status_t process_auth_eap(private_ike_auth_t *this, message_t *message)
if (this->initiator)
{
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- SIG_IKE(UP_SUCCESS, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
- this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_unique_id(this->ike_sa),
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
+ DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
return SUCCESS;
}
return NEED_MORE;
@@ -482,7 +484,7 @@ static status_t process_eap_i(private_ike_auth_t *this, message_t *message)
eap = (eap_payload_t*)message->get_payload(message, EXTENSIBLE_AUTHENTICATION);
if (eap == NULL)
{
- SIG_IKE(UP_FAILED, "EAP payload missing");
+ DBG1(DBG_IKE, "EAP payload missing");
return FAILED;
}
switch (this->eap_auth->process(this->eap_auth, eap, &eap))
@@ -498,7 +500,7 @@ static status_t process_eap_i(private_ike_auth_t *this, message_t *message)
return NEED_MORE;
default:
this->eap_payload = NULL;
- SIG_IKE(UP_FAILED, "failed to authenticate against '%D' using EAP",
+ DBG0(DBG_IKE, "failed to authenticate against '%D' using EAP",
this->ike_sa->get_other_id(this->ike_sa));
return FAILED;
}
@@ -533,7 +535,7 @@ static status_t build_eap_r(private_ike_auth_t *this, message_t *message)
if (this->eap_payload == NULL)
{
- SIG_IKE(UP_FAILED, "EAP payload missing");
+ DBG1(DBG_IKE, "EAP payload missing");
return FAILED;
}
@@ -548,9 +550,9 @@ static status_t build_eap_r(private_ike_auth_t *this, message_t *message)
this->public.task.process = (status_t(*)(task_t*,message_t*))process_auth_eap;
break;
default:
- SIG_IKE(UP_FAILED, "authentication of '%D' with %N failed",
- this->ike_sa->get_other_id(this->ike_sa),
- auth_class_names, AUTH_CLASS_EAP);
+ DBG0(DBG_IKE, "authentication of '%D' with %N failed",
+ this->ike_sa->get_other_id(this->ike_sa),
+ auth_class_names, AUTH_CLASS_EAP);
status = FAILED;
break;
}
@@ -665,9 +667,9 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
config = this->ike_sa->get_peer_cfg(this->ike_sa);
if (config == NULL)
{
- SIG_IKE(UP_FAILED, "no matching config found for '%D'...'%D'",
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
+ DBG1(DBG_IKE, "no matching config found for '%D'...'%D'",
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
return FAILED;
}
@@ -689,13 +691,13 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
if (this->peer_authenticated)
{
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- SIG_IKE(UP_SUCCESS, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
- this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_unique_id(this->ike_sa),
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
+ DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
return SUCCESS;
}
@@ -706,7 +708,7 @@ static status_t build_r(private_ike_auth_t *this, message_t *message)
message->add_payload(message, (payload_t*)eap_payload);
if (status != NEED_MORE)
{
- SIG_IKE(UP_FAILED, "unable to initiate EAP authentication");
+ DBG1(DBG_IKE, "unable to initiate EAP authentication");
return FAILED;
}
@@ -766,7 +768,7 @@ static status_t process_i(private_ike_auth_t *this, message_t *message)
{
if (type < 16383)
{
- SIG_IKE(UP_FAILED, "received %N notify error",
+ DBG1(DBG_IKE, "received %N notify error",
notify_type_names, type);
iterator->destroy(iterator);
return FAILED;
@@ -798,18 +800,18 @@ static status_t process_i(private_ike_auth_t *this, message_t *message)
auth = this->ike_sa->get_other_auth(this->ike_sa);
if (!auth->complies(auth, config->get_auth(config)))
{
- SIG_IKE(UP_FAILED, "authorization of '%D' for config %s failed",
+ DBG0(DBG_IKE, "authorization of '%D' for config %s failed",
this->ike_sa->get_other_id(this->ike_sa), config->get_name(config));
return FAILED;
}
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
- SIG_IKE(UP_SUCCESS, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
- this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_unique_id(this->ike_sa),
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
+ DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
return SUCCESS;
}
diff --git a/src/charon/sa/tasks/ike_auth_lifetime.c b/src/charon/sa/tasks/ike_auth_lifetime.c
index 2d18c6a1e..cb17cc2dc 100644
--- a/src/charon/sa/tasks/ike_auth_lifetime.c
+++ b/src/charon/sa/tasks/ike_auth_lifetime.c
@@ -12,11 +12,13 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_auth_lifetime.c 3589 2008-03-13 14:14:44Z martin $
+ * $Id: ike_auth_lifetime.c 4576 2008-11-05 08:32:38Z martin $
*/
#include "ike_auth_lifetime.h"
+#include <time.h>
+
#include <daemon.h>
#include <encoding/payloads/notify_payload.h>
@@ -47,9 +49,10 @@ static void add_auth_lifetime(private_ike_auth_lifetime_t *this, message_t *mess
chunk_t chunk;
u_int32_t lifetime;
- lifetime = this->ike_sa->get_statistic(this->ike_sa, STAT_REAUTH_TIME);
+ lifetime = this->ike_sa->get_statistic(this->ike_sa, STAT_REAUTH);
if (lifetime)
{
+ lifetime -= time(NULL);
chunk = chunk_from_thing(lifetime);
*(u_int32_t*)chunk.ptr = htonl(lifetime);
message->add_notify(message, FALSE, AUTH_LIFETIME, chunk);
diff --git a/src/charon/sa/tasks/ike_delete.c b/src/charon/sa/tasks/ike_delete.c
index 295f908cb..1c051853c 100644
--- a/src/charon/sa/tasks/ike_delete.c
+++ b/src/charon/sa/tasks/ike_delete.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_delete.c 4211 2008-07-23 18:46:34Z andreas $
+ * $Id: ike_delete.c 4458 2008-10-17 03:44:06Z andreas $
*/
#include "ike_delete.h"
@@ -56,21 +56,21 @@ static status_t build_i(private_ike_delete_t *this, message_t *message)
{
delete_payload_t *delete_payload;
- SIG_IKE(DOWN_START, "deleting IKE_SA %s[%d] between %H[%D]...%H[%D]",
- this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_unique_id(this->ike_sa),
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
+ DBG0(DBG_IKE, "deleting IKE_SA %s[%d] between %H[%D]...%H[%D]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
delete_payload = delete_payload_create(PROTO_IKE);
message->add_payload(message, (payload_t*)delete_payload);
this->ike_sa->set_state(this->ike_sa, IKE_DELETING);
DBG1(DBG_IKE, "sending DELETE for IKE_SA %s[%d]",
- this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_unique_id(this->ike_sa));
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa));
return NEED_MORE;
}
@@ -80,6 +80,7 @@ static status_t build_i(private_ike_delete_t *this, message_t *message)
*/
static status_t process_i(private_ike_delete_t *this, message_t *message)
{
+ DBG0(DBG_IKE, "IKE_SA deleted");
/* completed, delete IKE_SA by returning FAILED */
return FAILED;
}
@@ -92,15 +93,15 @@ static status_t process_r(private_ike_delete_t *this, message_t *message)
/* we don't even scan the payloads, as the message wouldn't have
* come so far without being correct */
DBG1(DBG_IKE, "received DELETE for IKE_SA %s[%d]",
- this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_unique_id(this->ike_sa));
- SIG_IKE(DOWN_START, "deleting IKE_SA %s[%d] between %H[%D]...%H[%D]",
- this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_unique_id(this->ike_sa),
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa));
+ DBG0(DBG_IKE, "deleting IKE_SA %s[%d] between %H[%D]...%H[%D]",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
switch (this->ike_sa->get_state(this->ike_sa))
{
@@ -123,7 +124,7 @@ static status_t process_r(private_ike_delete_t *this, message_t *message)
*/
static status_t build_r(private_ike_delete_t *this, message_t *message)
{
- SIG_IKE(DOWN_SUCCESS, "IKE_SA deleted");
+ DBG0(DBG_IKE, "IKE_SA deleted");
if (this->simultaneous)
{
diff --git a/src/charon/sa/tasks/ike_init.c b/src/charon/sa/tasks/ike_init.c
index 609b37a39..bd2cd39bb 100644
--- a/src/charon/sa/tasks/ike_init.c
+++ b/src/charon/sa/tasks/ike_init.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 Tobias Brunner
- * Copyright (C) 2005-2007 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: ike_init.c 4206 2008-07-22 17:10:10Z andreas $
+ * $Id: ike_init.c 4531 2008-10-30 12:58:54Z martin $
*/
#include "ike_init.h"
@@ -64,11 +64,16 @@ struct private_ike_init_t {
diffie_hellman_group_t dh_group;
/**
- * Diffie hellman object used to generate public DH value.
+ * diffie hellman key exchange
*/
diffie_hellman_t *dh;
/**
+ * Keymat derivation (from IKE_SA)
+ */
+ keymat_t *keymat;
+
+ /**
* nonce chosen by us
*/
chunk_t my_nonce;
@@ -192,7 +197,8 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
this->dh_group = ke_payload->get_dh_group_number(ke_payload);
if (!this->initiator)
{
- this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
+ this->dh = this->keymat->create_dh(this->keymat,
+ this->dh_group);
}
if (this->dh)
{
@@ -230,26 +236,26 @@ static status_t build_i(private_ike_init_t *this, message_t *message)
rng_t *rng;
this->config = this->ike_sa->get_ike_cfg(this->ike_sa);
- SIG_IKE(UP_START, "initiating IKE_SA %s[%d] to %H",
- this->ike_sa->get_name(this->ike_sa),
- this->ike_sa->get_unique_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa));
+ DBG0(DBG_IKE, "initiating IKE_SA %s[%d] to %H",
+ this->ike_sa->get_name(this->ike_sa),
+ this->ike_sa->get_unique_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa));
this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
if (this->retry++ >= MAX_RETRIES)
{
- SIG_IKE(UP_FAILED, "giving up after %d retries", MAX_RETRIES);
+ DBG1(DBG_IKE, "giving up after %d retries", MAX_RETRIES);
return FAILED;
}
-
+
/* if the DH group is set via use_dh_group(), we already have a DH object */
if (!this->dh)
{
this->dh_group = this->config->get_dh_group(this->config);
- this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
- if (this->dh == NULL)
+ this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
+ if (!this->dh)
{
- SIG_IKE(UP_FAILED, "configured DH group %N not supported",
+ DBG1(DBG_IKE, "configured DH group %N not supported",
diffie_hellman_group_names, this->dh_group);
return FAILED;
}
@@ -261,7 +267,7 @@ static status_t build_i(private_ike_init_t *this, message_t *message)
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
if (!rng)
{
- SIG_IKE(UP_FAILED, "error generating nonce");
+ DBG1(DBG_IKE, "error generating nonce");
return FAILED;
}
rng->allocate_bytes(rng, NONCE_SIZE, &this->my_nonce);
@@ -296,8 +302,7 @@ static status_t process_r(private_ike_init_t *this, message_t *message)
rng_t *rng;
this->config = this->ike_sa->get_ike_cfg(this->ike_sa);
- SIG_IKE(UP_START, "%H is initiating an IKE_SA",
- message->get_source(message));
+ DBG0(DBG_IKE, "%H is initiating an IKE_SA", message->get_source(message));
this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
@@ -369,30 +374,30 @@ static status_t process_r(private_ike_init_t *this, message_t *message)
*/
static status_t build_r(private_ike_init_t *this, message_t *message)
{
- chunk_t secret;
- status_t status;
-
+ keymat_t *old_keymat = NULL;
+ ike_sa_id_t *id;
+
/* check if we have everything we need */
if (this->proposal == NULL ||
this->other_nonce.len == 0 || this->my_nonce.len == 0)
{
- SIG_IKE(UP_FAILED, "received proposals inacceptable");
+ DBG1(DBG_IKE, "received proposals inacceptable");
message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
return FAILED;
}
+ this->ike_sa->set_proposal(this->ike_sa, this->proposal);
if (this->dh == NULL ||
- !this->proposal->has_dh_group(this->proposal, this->dh_group) ||
- this->dh->get_shared_secret(this->dh, &secret) != SUCCESS)
+ !this->proposal->has_dh_group(this->proposal, this->dh_group))
{
u_int16_t group;
if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
&group, NULL))
{
- SIG_CHD(UP_FAILED, NULL, "DH group %N inacceptable, requesting %N",
- diffie_hellman_group_names, this->dh_group,
- diffie_hellman_group_names, group);
+ DBG1(DBG_IKE, "DH group %N inacceptable, requesting %N",
+ diffie_hellman_group_names, this->dh_group,
+ diffie_hellman_group_names, group);
this->dh_group = group;
group = htons(group);
message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
@@ -400,49 +405,28 @@ static status_t build_r(private_ike_init_t *this, message_t *message)
}
else
{
- SIG_IKE(UP_FAILED, "no acceptable proposal found");
+ DBG1(DBG_IKE, "no acceptable proposal found");
}
return FAILED;
}
+ id = this->ike_sa->get_id(this->ike_sa);
if (this->old_sa)
- {
- ike_sa_id_t *id;
- prf_t *prf, *child_prf;
-
- /* Apply SPI if we are rekeying */
- id = this->ike_sa->get_id(this->ike_sa);
+ { /* rekeying: Apply SPI, include keymat from old SA in key derivation */
id->set_initiator_spi(id, this->proposal->get_spi(this->proposal));
-
- /* setup crypto keys for the rekeyed SA */
- prf = this->old_sa->get_prf(this->old_sa);
- child_prf = this->old_sa->get_child_prf(this->old_sa);
- status = this->ike_sa->derive_keys(this->ike_sa, this->proposal, secret,
- this->other_nonce, this->my_nonce,
- FALSE, child_prf, prf);
+ old_keymat = this->old_sa->get_keymat(this->old_sa);
}
- else
+ if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, this->dh,
+ this->other_nonce, this->my_nonce, id, old_keymat))
{
- /* setup crypto keys */
- status = this->ike_sa->derive_keys(this->ike_sa, this->proposal, secret,
- this->other_nonce, this->my_nonce,
- FALSE, NULL, NULL);
- }
- if (status != SUCCESS)
- {
- SIG_IKE(UP_FAILED, "key derivation failed");
+ DBG1(DBG_IKE, "key derivation failed");
message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
return FAILED;
}
-
- /* Keep the selected IKE proposal for status information purposes */
- {
- char buf[BUF_LEN];
-
- snprintf(buf, BUF_LEN, "%P", this->proposal);
- this->ike_sa->set_proposal(this->ike_sa, buf+4);
- }
-
+
+ charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh,
+ this->other_nonce, this->my_nonce, this->old_sa);
+
build_payloads(this, message);
return SUCCESS;
}
@@ -452,8 +436,8 @@ static status_t build_r(private_ike_init_t *this, message_t *message)
*/
static status_t process_i(private_ike_init_t *this, message_t *message)
{
- chunk_t secret;
- status_t status;
+ keymat_t *old_keymat = NULL;
+ ike_sa_id_t *id;
iterator_t *iterator;
payload_t *payload;
@@ -505,7 +489,7 @@ static status_t process_i(private_ike_init_t *this, message_t *message)
{
if (type < 16383)
{
- SIG_IKE(UP_FAILED, "received %N notify error",
+ DBG1(DBG_IKE, "received %N notify error",
notify_type_names, type);
iterator->destroy(iterator);
return FAILED;
@@ -525,55 +509,34 @@ static status_t process_i(private_ike_init_t *this, message_t *message)
if (this->proposal == NULL ||
this->other_nonce.len == 0 || this->my_nonce.len == 0)
{
- SIG_IKE(UP_FAILED, "peer's proposal selection invalid");
+ DBG1(DBG_IKE, "peers proposal selection invalid");
return FAILED;
}
+ this->ike_sa->set_proposal(this->ike_sa, this->proposal);
if (this->dh == NULL ||
- !this->proposal->has_dh_group(this->proposal, this->dh_group) ||
- this->dh->get_shared_secret(this->dh, &secret) != SUCCESS)
+ !this->proposal->has_dh_group(this->proposal, this->dh_group))
{
- SIG_IKE(UP_FAILED, "peer's DH group selection invalid");
+ DBG1(DBG_IKE, "peer DH group selection invalid");
return FAILED;
}
- /* Apply SPI if we are rekeying */
+ id = this->ike_sa->get_id(this->ike_sa);
if (this->old_sa)
- {
- ike_sa_id_t *id;
- prf_t *prf, *child_prf;
-
- id = this->ike_sa->get_id(this->ike_sa);
+ { /* rekeying: Apply SPI, include keymat from old SA in key derivation */
id->set_responder_spi(id, this->proposal->get_spi(this->proposal));
-
- /* setup crypto keys for the rekeyed SA */
- prf = this->old_sa->get_prf(this->old_sa);
- child_prf = this->old_sa->get_child_prf(this->old_sa);
- status = this->ike_sa->derive_keys(this->ike_sa, this->proposal, secret,
- this->my_nonce, this->other_nonce,
- TRUE, child_prf, prf);
+ old_keymat = this->old_sa->get_keymat(this->old_sa);
}
- else
+ if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, this->dh,
+ this->my_nonce, this->other_nonce, id, old_keymat))
{
- /* setup crypto keys for a new SA */
- status = this->ike_sa->derive_keys(this->ike_sa, this->proposal, secret,
- this->my_nonce, this->other_nonce,
- TRUE, NULL, NULL);
- }
- if (status != SUCCESS)
- {
- SIG_IKE(UP_FAILED, "key derivation failed");
+ DBG1(DBG_IKE, "key derivation failed");
return FAILED;
}
-
- /* Keep the selected IKE proposal for status information purposes */
- {
- char buf[BUF_LEN];
-
- snprintf(buf, BUF_LEN, "%P", this->proposal);
- this->ike_sa->set_proposal(this->ike_sa, buf+4);
- }
-
+
+ charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh,
+ this->my_nonce, this->other_nonce, this->old_sa);
+
return SUCCESS;
}
@@ -607,12 +570,12 @@ static chunk_t get_lower_nonce(private_ike_init_t *this)
static void migrate(private_ike_init_t *this, ike_sa_t *ike_sa)
{
DESTROY_IF(this->proposal);
- DESTROY_IF(this->dh);
chunk_free(&this->other_nonce);
this->ike_sa = ike_sa;
this->proposal = NULL;
- this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group);
+ DESTROY_IF(this->dh);
+ this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
}
/**
@@ -620,8 +583,8 @@ static void migrate(private_ike_init_t *this, ike_sa_t *ike_sa)
*/
static void destroy(private_ike_init_t *this)
{
- DESTROY_IF(this->proposal);
DESTROY_IF(this->dh);
+ DESTROY_IF(this->proposal);
chunk_free(&this->my_nonce);
chunk_free(&this->other_nonce);
chunk_free(&this->cookie);
@@ -654,6 +617,7 @@ ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa)
this->initiator = initiator;
this->dh_group = MODP_NONE;
this->dh = NULL;
+ this->keymat = ike_sa->get_keymat(ike_sa);
this->my_nonce = chunk_empty;
this->other_nonce = chunk_empty;
this->cookie = chunk_empty;
diff --git a/src/charon/sa/tasks/ike_me.c b/src/charon/sa/tasks/ike_me.c
index a203dee58..f58d51341 100644
--- a/src/charon/sa/tasks/ike_me.c
+++ b/src/charon/sa/tasks/ike_me.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_me.c 4355 2008-09-25 07:56:58Z tobias $
+ * $Id: ike_me.c 4640 2008-11-12 16:07:17Z martin $
*/
#include "ike_me.h"
@@ -461,8 +461,7 @@ static status_t process_i(private_ike_me_t *this, message_t *message)
this->ike_sa->set_server_reflexive_host(this->ike_sa, endpoint->clone(endpoint));
}
/* FIXME: what if it failed? e.g. AUTH failure */
- SIG_CHD(UP_SUCCESS, NULL, "established mediation connection "
- "without CHILD_SA successfully");
+ DBG1(DBG_IKE, "established mediation connection successfully");
break;
}
@@ -642,8 +641,7 @@ static status_t build_r_ms(private_ike_me_t *this, message_t *message)
/* FIXME: we actually must delete any existing IKE_SAs with the same remote id */
this->ike_sa->act_as_mediation_server(this->ike_sa);
- SIG_CHD(UP_SUCCESS, NULL, "established mediation connection "
- "without CHILD_SA successfully");
+ DBG1(DBG_IKE, "established mediation connection successfully");
break;
}
@@ -787,7 +785,7 @@ ike_me_t *ike_me_create(ike_sa_t *ike_sa, bool initiator)
this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
this->public.task.destroy = (void(*)(task_t*))destroy;
- if (ike_sa->is_ike_initiator(ike_sa))
+ if (ike_sa->has_condition(ike_sa, COND_ORIGINAL_INITIATOR))
{
if (initiator)
{
diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c
index f6ee3f6ad..a791d1892 100644
--- a/src/charon/sa/tasks/ike_mobike.c
+++ b/src/charon/sa/tasks/ike_mobike.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_mobike.c 4394 2008-10-09 08:25:11Z martin $
+ * $Id: ike_mobike.c 4618 2008-11-11 09:22:00Z tobias $
*/
#include "ike_mobike.h"
@@ -251,10 +251,16 @@ static void update_children(private_ike_mobike_t *this)
iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa);
while (iterator->iterate(iterator, (void**)&child_sa))
{
- child_sa->update_hosts(child_sa,
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
+ if (child_sa->update_hosts(child_sa,
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_virtual_ip(this->ike_sa, TRUE),
+ this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)) == NOT_SUPPORTED)
+ {
+ this->ike_sa->rekey_child_sa(this->ike_sa,
+ child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE));
+ }
}
iterator->destroy(iterator);
}
diff --git a/src/charon/sa/tasks/ike_reauth.c b/src/charon/sa/tasks/ike_reauth.c
index b84b2a387..61701075f 100644
--- a/src/charon/sa/tasks/ike_reauth.c
+++ b/src/charon/sa/tasks/ike_reauth.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2007 Martin Willi
+ * Copyright (C) 2006-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_reauth.c 4211 2008-07-23 18:46:34Z andreas $
+ * $Id: ike_reauth.c 4495 2008-10-28 16:07:06Z martin $
*/
#include "ike_reauth.h"
@@ -65,7 +65,6 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message)
/* process delete response first */
this->ike_delete->task.process(&this->ike_delete->task, message);
- SIG_IKE(DOWN_SUCCESS, "IKE_SA deleted");
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
@@ -105,6 +104,8 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message)
{
charon->ike_sa_manager->checkin_and_destroy(
charon->ike_sa_manager, new);
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
return FAILED;
}
@@ -132,6 +133,8 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message)
iterator->destroy(iterator);
charon->ike_sa_manager->checkin_and_destroy(
charon->ike_sa_manager, new);
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
return FAILED;
}
@@ -141,6 +144,8 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message)
}
iterator->destroy(iterator);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
/* we always return failed to delete the obsolete IKE_SA */
return FAILED;
diff --git a/src/charon/sa/tasks/ike_rekey.c b/src/charon/sa/tasks/ike_rekey.c
index 6c4ef4354..28d63cca7 100644
--- a/src/charon/sa/tasks/ike_rekey.c
+++ b/src/charon/sa/tasks/ike_rekey.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: ike_rekey.c 4211 2008-07-23 18:46:34Z andreas $
+ * $Id: ike_rekey.c 4659 2008-11-14 14:05:47Z martin $
*/
#include "ike_rekey.h"
@@ -144,7 +144,7 @@ static status_t build_r(private_ike_rekey_t *this, message_t *message)
message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
return SUCCESS;
}
-
+
if (this->ike_init->task.build(&this->ike_init->task, message) == FAILED)
{
return SUCCESS;
@@ -152,13 +152,13 @@ static status_t build_r(private_ike_rekey_t *this, message_t *message)
this->ike_sa->set_state(this->ike_sa, IKE_REKEYING);
this->new_sa->set_state(this->new_sa, IKE_ESTABLISHED);
- SIG_IKE(UP_SUCCESS, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
- this->new_sa->get_name(this->new_sa),
- this->new_sa->get_unique_id(this->new_sa),
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
+ DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
+ this->new_sa->get_name(this->new_sa),
+ this->new_sa->get_unique_id(this->new_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
return SUCCESS;
}
@@ -170,7 +170,32 @@ static status_t process_i(private_ike_rekey_t *this, message_t *message)
{
job_t *job;
ike_sa_id_t *to_delete;
+ iterator_t *iterator;
+ payload_t *payload;
+ /* handle NO_ADDITIONAL_SAS notify */
+ iterator = message->get_payload_iterator(message);
+ while (iterator->iterate(iterator, (void**)&payload))
+ {
+ if (payload->get_type(payload) == NOTIFY)
+ {
+ notify_payload_t *notify = (notify_payload_t*)payload;
+
+ if (notify->get_notify_type(notify) == NO_ADDITIONAL_SAS)
+ {
+ DBG1(DBG_IKE, "peer seems to not support IKE rekeying, "
+ "starting reauthentication");
+ this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
+ charon->processor->queue_job(charon->processor,
+ (job_t*)rekey_ike_sa_job_create(
+ this->ike_sa->get_id(this->ike_sa), TRUE));
+ iterator->destroy(iterator);
+ return SUCCESS;
+ }
+ }
+ }
+ iterator->destroy(iterator);
+
switch (this->ike_init->task.process(&this->ike_init->task, message))
{
case FAILED:
@@ -198,13 +223,13 @@ static status_t process_i(private_ike_rekey_t *this, message_t *message)
}
this->new_sa->set_state(this->new_sa, IKE_ESTABLISHED);
- SIG_IKE(UP_SUCCESS, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
- this->new_sa->get_name(this->new_sa),
- this->new_sa->get_unique_id(this->new_sa),
- this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_my_id(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_other_id(this->ike_sa));
+ DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%D]...%H[%D]",
+ this->new_sa->get_name(this->new_sa),
+ this->new_sa->get_unique_id(this->new_sa),
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_my_id(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa),
+ this->ike_sa->get_other_id(this->ike_sa));
to_delete = this->ike_sa->get_id(this->ike_sa);
@@ -242,6 +267,8 @@ static status_t process_i(private_ike_rekey_t *this, message_t *message)
this->new_sa = other->new_sa;
other->new_sa = NULL;
}
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
}
job = (job_t*)delete_ike_sa_job_create(to_delete, TRUE);
@@ -277,6 +304,8 @@ static void migrate(private_ike_rekey_t *this, ike_sa_t *ike_sa)
{
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
this->new_sa);
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
}
DESTROY_IF(this->collision);
@@ -303,6 +332,8 @@ static void destroy(private_ike_rekey_t *this)
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
this->new_sa);
}
+ /* set threads active IKE_SA after checkin */
+ charon->bus->set_sa(charon->bus, this->ike_sa);
}
if (this->ike_init)
{
diff --git a/src/charon/sa/tasks/task.c b/src/charon/sa/tasks/task.c
index 3192b688a..fd15379f3 100644
--- a/src/charon/sa/tasks/task.c
+++ b/src/charon/sa/tasks/task.c
@@ -13,11 +13,12 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: task.c 3666 2008-03-26 18:40:19Z tobias $
+ * $Id: task.c 4618 2008-11-11 09:22:00Z tobias $
*/
#include "task.h"
+#ifdef ME
ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
"IKE_INIT",
"IKE_NATD",
@@ -31,11 +32,27 @@ ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
"IKE_REAUTH",
"IKE_DELETE",
"IKE_DPD",
-#ifdef ME
"IKE_ME",
-#endif /* ME */
"CHILD_CREATE",
"CHILD_DELETE",
"CHILD_REKEY",
);
-
+#else
+ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
+ "IKE_INIT",
+ "IKE_NATD",
+ "IKE_MOBIKE",
+ "IKE_AUTHENTICATE",
+ "IKE_AUTH_LIFETIME",
+ "IKE_CERT_PRE",
+ "IKE_CERT_POST",
+ "IKE_CONFIG",
+ "IKE_REKEY",
+ "IKE_REAUTH",
+ "IKE_DELETE",
+ "IKE_DPD",
+ "CHILD_CREATE",
+ "CHILD_DELETE",
+ "CHILD_REKEY",
+);
+#endif /* ME */
diff --git a/src/dumm/Makefile.am b/src/dumm/Makefile.am
index 11d65bba9..029290fb6 100644
--- a/src/dumm/Makefile.am
+++ b/src/dumm/Makefile.am
@@ -11,8 +11,8 @@ irdumm_SOURCES = irdumm.c
libdumm_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la \
-lbridge -lfuse -lutil
-dumm_LDADD = -ldumm ${gtk_LIBS}
-irdumm_LDADD = -ldumm -lruby1.8
+dumm_LDADD = libdumm.la ${gtk_LIBS}
+irdumm_LDADD = libdumm.la -lruby1.8
INCLUDES = -I$(top_srcdir)/src/libstrongswan ${gtk_CFLAGS} \
-I/usr/lib/ruby/1.8/i486-linux/
diff --git a/src/dumm/Makefile.in b/src/dumm/Makefile.in
index 333e616d3..7c3f28191 100644
--- a/src/dumm/Makefile.in
+++ b/src/dumm/Makefile.in
@@ -61,10 +61,10 @@ PROGRAMS = $(ipsec_PROGRAMS)
am_dumm_OBJECTS = main.$(OBJEXT)
dumm_OBJECTS = $(am_dumm_OBJECTS)
am__DEPENDENCIES_1 =
-dumm_DEPENDENCIES = $(am__DEPENDENCIES_1)
+dumm_DEPENDENCIES = libdumm.la $(am__DEPENDENCIES_1)
am_irdumm_OBJECTS = irdumm.$(OBJEXT)
irdumm_OBJECTS = $(am_irdumm_OBJECTS)
-irdumm_DEPENDENCIES =
+irdumm_DEPENDENCIES = libdumm.la
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -230,8 +230,8 @@ irdumm_SOURCES = irdumm.c
libdumm_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la \
-lbridge -lfuse -lutil
-dumm_LDADD = -ldumm ${gtk_LIBS}
-irdumm_LDADD = -ldumm -lruby1.8
+dumm_LDADD = libdumm.la ${gtk_LIBS}
+irdumm_LDADD = libdumm.la -lruby1.8
INCLUDES = -I$(top_srcdir)/src/libstrongswan ${gtk_CFLAGS} \
-I/usr/lib/ruby/1.8/i486-linux/
diff --git a/src/dumm/dumm.c b/src/dumm/dumm.c
index eaefddb60..cf8d9719c 100644
--- a/src/dumm/dumm.c
+++ b/src/dumm/dumm.c
@@ -87,7 +87,7 @@ static void delete_guest(private_dumm_t *this, guest_t *guest)
guest->destroy(guest);
if (len > 8 && len < 512)
{
- system(buf);
+ ignore_result(system(buf));
}
}
}
@@ -280,7 +280,10 @@ dumm_t *dumm_create(char *dir)
}
if (dir)
{
- asprintf(&this->dir, "%s/%s", cwd, dir);
+ if (asprintf(&this->dir, "%s/%s", cwd, dir) < 0)
+ {
+ this->dir = NULL;
+ }
}
else
{
@@ -288,17 +291,21 @@ dumm_t *dumm_create(char *dir)
}
}
this->template = NULL;
- asprintf(&this->guest_dir, "%s/%s", this->dir, GUEST_DIR);
+ if (asprintf(&this->guest_dir, "%s/%s", this->dir, GUEST_DIR) < 0)
+ {
+ this->guest_dir = NULL;
+ }
this->guests = linked_list_create();
this->bridges = linked_list_create();
- if (mkdir(this->guest_dir, PERME) < 0 && errno != EEXIST)
+ if (this->dir == NULL || this->guest_dir == NULL ||
+ (mkdir(this->guest_dir, PERME) < 0 && errno != EEXIST))
{
DBG1("creating guest directory '%s' failed: %m", this->guest_dir);
destroy(this);
return NULL;
}
-
+
load_guests(this);
return &this->public;
}
diff --git a/src/dumm/ext/dumm.c b/src/dumm/ext/dumm.c
index 97f14ef85..2610affc3 100644
--- a/src/dumm/ext/dumm.c
+++ b/src/dumm/ext/dumm.c
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: dumm.c 4410 2008-10-10 11:20:04Z martin $
+ * $Id: dumm.c 4447 2008-10-15 14:47:52Z martin $
*/
#include <stdio.h>
@@ -207,6 +207,22 @@ static VALUE guest_exec(VALUE self, VALUE cmd)
block = rb_block_given_p();
Data_Get_Struct(self, guest_t, guest);
if ((ret = guest->exec_str(guest, block ? (void*)exec_cb : NULL, TRUE, NULL,
+ "exec %s", StringValuePtr(cmd))) != 0)
+ {
+ rb_raise(rb_eRuntimeError, "executing command failed (%d)", ret);
+ }
+ return self;
+}
+
+static VALUE guest_mconsole(VALUE self, VALUE cmd)
+{
+ guest_t *guest;
+ bool block;
+ int ret;
+
+ block = rb_block_given_p();
+ Data_Get_Struct(self, guest_t, guest);
+ if ((ret = guest->exec_str(guest, block ? (void*)exec_cb : NULL, TRUE, NULL,
"%s", StringValuePtr(cmd))) != 0)
{
rb_raise(rb_eRuntimeError, "executing command failed (%d)", ret);
@@ -310,6 +326,7 @@ static void guest_init()
rb_define_method(rbc_guest, "stop", guest_stop, 0);
rb_define_method(rbc_guest, "running?", guest_running, 0);
rb_define_method(rbc_guest, "exec", guest_exec, 1);
+ rb_define_method(rbc_guest, "mconsole", guest_mconsole, 1);
rb_define_method(rbc_guest, "add", guest_add_iface, 1);
rb_define_method(rbc_guest, "[]", guest_get_iface, 1);
rb_define_method(rbc_guest, "each", guest_each_iface, -1);
diff --git a/src/dumm/guest.c b/src/dumm/guest.c
index aed2a3e18..014a9113f 100644
--- a/src/dumm/guest.c
+++ b/src/dumm/guest.c
@@ -576,11 +576,22 @@ static private_guest_t *guest_create_generic(char *parent, char *name,
if (*parent == '/' || getcwd(cwd, sizeof(cwd)) == NULL)
{
- asprintf(&this->dirname, "%s/%s", parent, name);
+ if (asprintf(&this->dirname, "%s/%s", parent, name) < 0)
+ {
+ this->dirname = NULL;
+ }
}
else
{
- asprintf(&this->dirname, "%s/%s/%s", cwd, parent, name);
+ if (asprintf(&this->dirname, "%s/%s/%s", cwd, parent, name) < 0)
+ {
+ this->dirname = NULL;
+ }
+ }
+ if (this->dirname == NULL)
+ {
+ free(this);
+ return NULL;
}
if (create)
{
diff --git a/src/dumm/guest.h b/src/dumm/guest.h
index 0e48b1d06..19dc8a8bf 100644
--- a/src/dumm/guest.h
+++ b/src/dumm/guest.h
@@ -142,7 +142,7 @@ struct guest_t {
bool (*load_template)(guest_t *this, char *parent);
/**
- * Execute a command in the guest.
+ * Execute a command on the guests mconsole.
*
* @param cb callback to call for each read block
* @param data data to pass to callback
@@ -154,20 +154,22 @@ struct guest_t {
char *cmd, ...);
/**
- * Execute a command in the guest and return the output by lines or as combined
- * string.
+ * Execute a command on the guests mconsole, with output formatter.
*
- * @note This function does not work with binary output (i.e. containing 0 bytes).
+ * If lines is TRUE, callback is invoked for each output line. Otherwise
+ * the full result is returned in one callback invocation.
+ *
+ * @note This function does not work with binary output.
*
* @param cb callback to call for each line or for the complete output
- * @param lines TRUE if the callback should be called for each line (instead of for the combined output)
+ * @param lines TRUE if the callback should be called for each line
* @param data data to pass to callback
* @param cmd command to execute
* @param ... printf style argument list for cmd
* @return return value
*/
int (*exec_str)(guest_t *this, void(*cb)(void*,char*), bool lines,
- void *data, char *cmd, ...);
+ void *data, char *cmd, ...);
/**
* @brief Called whenever a SIGCHILD for the guests PID is received.
diff --git a/src/dumm/iface.c b/src/dumm/iface.c
index 78c6c7c92..bf73c82a5 100644
--- a/src/dumm/iface.c
+++ b/src/dumm/iface.c
@@ -104,8 +104,8 @@ static char* get_hostif(private_iface_t *this)
*/
static bool add_address(private_iface_t *this, host_t *addr)
{
- return (this->guest->exec(this->guest, NULL, NULL, "ip addr add %H dev %s",
- addr, this->guestif) == 0);
+ return (this->guest->exec(this->guest, NULL, NULL,
+ "exec ip addr add %H dev %s", addr, this->guestif) == 0);
}
/**
@@ -136,7 +136,7 @@ static enumerator_t* create_address_enumerator(private_iface_t *this)
linked_list_t *addresses = linked_list_create();
this->guest->exec_str(this->guest, (void(*)(void*,char*))compile_address_list,
TRUE, addresses,
- "ip addr list dev %s scope global | "
+ "exec ip addr list dev %s scope global | "
"grep '^ \\+\\(inet6\\? \\)' | "
"awk -F '( +|/)' '{ print $3 }'", this->guestif);
return enumerator_create_cleaner(addresses->create_enumerator(addresses),
@@ -149,7 +149,7 @@ static enumerator_t* create_address_enumerator(private_iface_t *this)
static bool delete_address(private_iface_t *this, host_t *addr)
{
return (this->guest->exec(this->guest, NULL, NULL,
- "ip addr del %H dev %s", addr, this->guestif) == 0);
+ "exec ip addr del %H dev %s", addr, this->guestif) == 0);
}
/**
@@ -160,12 +160,12 @@ static void set_bridge(private_iface_t *this, bridge_t *bridge)
if (this->bridge == NULL && bridge)
{
this->guest->exec(this->guest, NULL, NULL,
- "ip link set %s up", this->guestif);
+ "exec ip link set %s up", this->guestif);
}
else if (this->bridge && bridge == NULL)
{
this->guest->exec(this->guest, NULL, NULL,
- "ip link set %s down", this->guestif);
+ "exec ip link set %s down", this->guestif);
}
this->bridge = bridge;
}
diff --git a/src/dumm/main.c b/src/dumm/main.c
index e2f2fc255..ba2801760 100644
--- a/src/dumm/main.c
+++ b/src/dumm/main.c
@@ -19,6 +19,7 @@
#include <sys/types.h>
#include <unistd.h>
+#include <sched.h>
#include <glib.h>
#include <gtk/gtk.h>
diff --git a/src/dumm/mconsole.c b/src/dumm/mconsole.c
index c6e0c2f08..02db5ab7e 100644
--- a/src/dumm/mconsole.c
+++ b/src/dumm/mconsole.c
@@ -201,13 +201,13 @@ static bool del_iface(private_mconsole_t *this, char *guest)
static int exec(private_mconsole_t *this, void(*cb)(void*,char*,size_t),
void *data, char *cmd)
{
- return request(this, cb, data, "exec %s", cmd);
+ return request(this, cb, data, "%s", cmd);
}
/**
* Poll until guest is ready
*/
-static bool wait_bootup(private_mconsole_t *this)
+static void wait_bootup(private_mconsole_t *this)
{
/* wait for init process to appear */
while (request(this, ignore, NULL, "exec ps -p 1 > /dev/null"))
@@ -247,7 +247,7 @@ static bool wait_for_notify(private_mconsole_t *this, char *nsock)
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, nsock, sizeof(addr));
+ strncpy(addr.sun_path, nsock, sizeof(addr.sun_path));
if (bind(this->notify, (struct sockaddr*)&addr, sizeof(addr)) < 0)
{
DBG1("binding mconsole notify socket to '%s' failed: %m", nsock);
@@ -306,7 +306,7 @@ static bool setup_console(private_mconsole_t *this)
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
- snprintf(&addr.sun_path[1], sizeof(addr.sun_path), "%5d-%d",
+ snprintf(&addr.sun_path[1], sizeof(addr.sun_path)-1, "%5d-%d",
getpid(), this->console);
if (bind(this->console, (struct sockaddr*)&addr, sizeof(addr)) < 0)
{
@@ -346,11 +346,7 @@ mconsole_t *mconsole_create(char *notify, void(*idle)(void))
}
unlink(notify);
- if (!wait_bootup(this))
- {
- destroy(this);
- return NULL;
- }
+ wait_bootup(this);
return &this->public;
}
diff --git a/src/dumm/mconsole.h b/src/dumm/mconsole.h
index 329c40c06..e8493b5bb 100644
--- a/src/dumm/mconsole.h
+++ b/src/dumm/mconsole.h
@@ -43,7 +43,7 @@ struct mconsole_t {
bool (*del_iface)(mconsole_t *this, char *guest);
/**
- * Execute a command in the UML host.
+ * Execute a command on the mconsole.
*
* @param cb callback function to invoke for each line
* @param data data to pass to callback
diff --git a/src/include/linux/ipsec.h b/src/include/linux/ipsec.h
index 81ac63a18..d17a6302a 100644
--- a/src/include/linux/ipsec.h
+++ b/src/include/linux/ipsec.h
@@ -3,7 +3,7 @@
/* The definitions, required to talk to KAME racoon IKE. */
-#include "pfkeyv2.h"
+#include <linux/pfkeyv2.h>
#define IPSEC_PORT_ANY 0
#define IPSEC_ULPROTO_ANY 255
@@ -12,7 +12,8 @@
enum {
IPSEC_MODE_ANY = 0, /* We do not support this for SA */
IPSEC_MODE_TRANSPORT = 1,
- IPSEC_MODE_TUNNEL = 2
+ IPSEC_MODE_TUNNEL = 2,
+ IPSEC_MODE_BEET = 3
};
enum {
diff --git a/src/include/linux/pfkeyv2.h b/src/include/linux/pfkeyv2.h
index 4de9d7761..b4b0712a4 100644
--- a/src/include/linux/pfkeyv2.h
+++ b/src/include/linux/pfkeyv2.h
@@ -226,6 +226,15 @@ struct sadb_x_sec_ctx {
} __attribute__((packed));
/* sizeof(struct sadb_sec_ctx) = 8 */
+/* Used by MIGRATE to pass addresses IKE will use to perform
+ * negotiation with the peer */
+struct sadb_x_kmaddress {
+ uint16_t sadb_x_kmaddress_len;
+ uint16_t sadb_x_kmaddress_exttype;
+ uint32_t sadb_x_kmaddress_reserved;
+} __attribute__((packed));
+/* sizeof(struct sadb_x_kmaddress) == 8 */
+
/* Message types */
#define SADB_RESERVED 0
#define SADB_GETSPI 1
@@ -298,6 +307,13 @@ struct sadb_x_sec_ctx {
#define SADB_X_EALG_BLOWFISHCBC 7
#define SADB_EALG_NULL 11
#define SADB_X_EALG_AESCBC 12
+#define SADB_X_EALG_AESCTR 13
+#define SADB_X_EALG_AES_CCM_ICV8 14
+#define SADB_X_EALG_AES_CCM_ICV12 15
+#define SADB_X_EALG_AES_CCM_ICV16 16
+#define SADB_X_EALG_AES_GCM_ICV8 18
+#define SADB_X_EALG_AES_GCM_ICV12 19
+#define SADB_X_EALG_AES_GCM_ICV16 20
#define SADB_X_EALG_CAMELLIACBC 22
#define SADB_EALG_MAX 253 /* last EALG */
/* private allocations should use 249-255 (RFC2407) */
@@ -339,7 +355,9 @@ struct sadb_x_sec_ctx {
#define SADB_X_EXT_NAT_T_DPORT 22
#define SADB_X_EXT_NAT_T_OA 23
#define SADB_X_EXT_SEC_CTX 24
-#define SADB_EXT_MAX 24
+/* Used with MIGRATE to pass @ to IKE for negotiation */
+#define SADB_X_EXT_KMADDRESS 25
+#define SADB_EXT_MAX 25
/* Identity Extension values */
#define SADB_IDENTTYPE_RESERVED 0
diff --git a/src/include/linux/xfrm.h b/src/include/linux/xfrm.h
index 759885cb6..52f3abd45 100644
--- a/src/include/linux/xfrm.h
+++ b/src/include/linux/xfrm.h
@@ -282,6 +282,7 @@ enum xfrm_attr_type_t {
XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */
XFRMA_MIGRATE,
XFRMA_ALG_AEAD, /* struct xfrm_algo_aead */
+ XFRMA_KMADDRESS, /* struct xfrm_user_kmaddress */
__XFRMA_MAX
#define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -418,6 +419,15 @@ struct xfrm_user_report {
struct xfrm_selector sel;
};
+/* Used by MIGRATE to pass addresses IKE should use to perform
+ * SA negotiation with the peer */
+struct xfrm_user_kmaddress {
+ xfrm_address_t local;
+ xfrm_address_t remote;
+ __u32 reserved;
+ __u16 family;
+};
+
struct xfrm_user_migrate {
xfrm_address_t old_daddr;
xfrm_address_t old_saddr;
diff --git a/src/libfreeswan/freeswan.h b/src/libfreeswan/freeswan.h
index 59e6f0d9b..cbb8e2db4 100644
--- a/src/libfreeswan/freeswan.h
+++ b/src/libfreeswan/freeswan.h
@@ -14,7 +14,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
* License for more details.
*
- * RCSID $Id: freeswan.h 3265 2007-10-08 19:52:55Z andreas $
+ * RCSID $Id: freeswan.h 4632 2008-11-11 18:37:19Z martin $
*/
#define _FREESWAN_H /* seen it, no need to see it again */
@@ -446,6 +446,7 @@ bitstomask(
/* option pickup from files (userland only because of use of FILE) */
const char *optionsfrom(const char *filename, int *argcp, char ***argvp,
int optind, FILE *errorreport);
+#define ignore_result(call) { if (call); }
#endif
/*
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_ @}*/
diff --git a/src/pluto/ac.c b/src/pluto/ac.c
index 77e0b40bb..6745ff484 100644
--- a/src/pluto/ac.c
+++ b/src/pluto/ac.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: ac.c 3686 2008-03-28 11:48:14Z martin $
+ * RCSID $Id: ac.c 4632 2008-11-11 18:37:19Z martin $
*/
#include <stdlib.h>
@@ -860,7 +860,7 @@ load_acerts(void)
}
}
/* restore directory path */
- chdir(save_dir);
+ ignore_result(chdir(save_dir));
}
/*
diff --git a/src/pluto/ca.c b/src/pluto/ca.c
index 099699056..70b26c32c 100644
--- a/src/pluto/ca.c
+++ b/src/pluto/ca.c
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: ca.c 3252 2007-10-06 21:24:50Z andreas $
+ * RCSID $Id: ca.c 4632 2008-11-11 18:37:19Z martin $
*/
#include <stdlib.h>
@@ -295,7 +295,7 @@ load_authcerts(const char *type, const char *path, u_char auth_flags)
}
}
/* restore directory path */
- chdir(save_dir);
+ ignore_result(chdir(save_dir));
}
/*
diff --git a/src/pluto/constants.c b/src/pluto/constants.c
index ca548afab..50a75c0aa 100644
--- a/src/pluto/constants.c
+++ b/src/pluto/constants.c
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: constants.c 3839 2008-04-18 11:25:37Z andreas $
+ * RCSID $Id: constants.c 4612 2008-11-11 06:37:37Z andreas $
*/
/*
@@ -517,6 +517,8 @@ const char *const sa_policy_bit_names[] = {
"DONTREAUTH",
"BEET",
"MOBIKE",
+ "ECDSA",
+ "PROXY",
NULL
};
diff --git a/src/pluto/constants.h b/src/pluto/constants.h
index e6357164f..409dd1d61 100644
--- a/src/pluto/constants.h
+++ b/src/pluto/constants.h
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: constants.h 4051 2008-06-10 09:08:27Z tobias $
+ * RCSID $Id: constants.h 4612 2008-11-11 06:37:37Z andreas $
*/
#ifndef _CONSTANTS_H
@@ -279,7 +279,7 @@ extern const char sparse_end[];
"4009438B 481C6CD7 889A002E D5EE382B C9190DA6 FC026E47" \
"9558E447 5677E9AA 9E3050E2 765694DF C81F56E8 80B96E71" \
"60C980DD 98EDD3DF FFFFFFFF FFFFFFFF"
-#define LOCALSECRETSIZE (256 / BITS_PER_BYTE)
+#define LOCALSECRETSIZE (512 / BITS_PER_BYTE)
/* limits on nonce sizes. See RFC2409 "The internet key exchange (IKE)" 5 */
#define MINIMUM_NONCE_SIZE 8 /* bytes */
@@ -877,7 +877,8 @@ extern const char *prettypolicy(lset_t policy);
#define POLICY_BEET LELEM(22) /* bound end2end tunnel, IKEv2 */
#define POLICY_MOBIKE LELEM(23) /* enable MOBIKE for IKEv2 */
#define POLICY_FORCE_ENCAP LELEM(24) /* force UDP encapsulation (IKEv2) */
-#define POLICY_ECDSASIG LELEM(25) /* ecdsa signature (IKEv2) */
+#define POLICY_ECDSASIG LELEM(25) /* ECDSA signature (IKEv2) */
+#define POLICY_PROXY LELEM(26) /* proxy transport mode (MIPv6) */
/* Any IPsec policy? If not, a connection description
* is only for ISAKMP SA, not IPSEC SA. (A pun, I admit.)
diff --git a/src/pluto/crl.c b/src/pluto/crl.c
index 6e1093661..c891d19e6 100644
--- a/src/pluto/crl.c
+++ b/src/pluto/crl.c
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: crl.c 3686 2008-03-28 11:48:14Z martin $
+ * RCSID $Id: crl.c 4632 2008-11-11 18:37:19Z martin $
*/
#include <stdlib.h>
@@ -373,7 +373,7 @@ load_crls(void)
}
}
/* restore directory path */
- chdir(save_dir);
+ ignore_result(chdir(save_dir));
}
/*
diff --git a/src/pluto/defs.c b/src/pluto/defs.c
index 5b9defb60..f2c1eab48 100644
--- a/src/pluto/defs.c
+++ b/src/pluto/defs.c
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: defs.c 3252 2007-10-06 21:24:50Z andreas $
+ * RCSID $Id: defs.c 4632 2008-11-11 18:37:19Z martin $
*/
#include <stdlib.h>
@@ -249,6 +249,7 @@ write_chunk(const char *filename, const char *label, chunk_t ch
{
mode_t oldmask;
FILE *fd;
+ size_t written;
if (!force)
{
@@ -268,8 +269,14 @@ write_chunk(const char *filename, const char *label, chunk_t ch
if (fd)
{
- fwrite(ch.ptr, sizeof(u_char), ch.len, fd);
+ written = fwrite(ch.ptr, sizeof(u_char), ch.len, fd);
fclose(fd);
+ if (written != ch.len)
+ {
+ plog(" writing to %s file '%s' failed", label, filename);
+ umask(oldmask);
+ return FALSE;
+ }
plog(" written %s file '%s' (%d bytes)", label, filename, (int)ch.len);
umask(oldmask);
return TRUE;
diff --git a/src/pluto/fetch.c b/src/pluto/fetch.c
index cd8b58df2..c8a98cd9b 100644
--- a/src/pluto/fetch.c
+++ b/src/pluto/fetch.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: fetch.c 3686 2008-03-28 11:48:14Z martin $
+ * RCSID $Id: fetch.c 4632 2008-11-11 18:37:19Z martin $
*/
#include <stdlib.h>
@@ -324,7 +324,7 @@ fetch_curl(char *url, chunk_t *blob)
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_buffer);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
- curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &errorbuffer);
+ curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, TRUE);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, FETCH_CMD_TIMEOUT);
@@ -705,9 +705,9 @@ fetch_ocsp_status(ocsp_location_t* location)
curl_easy_setopt(curl, CURLOPT_URL, uri);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_buffer);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request.ptr);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void*)request.ptr);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, request.len);
- curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &errorbuffer);
+ curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, TRUE);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, FETCH_CMD_TIMEOUT);
diff --git a/src/pluto/vendor.c b/src/pluto/vendor.c
index 1db4027d1..e4fda0f1f 100644
--- a/src/pluto/vendor.c
+++ b/src/pluto/vendor.c
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: vendor.c 4348 2008-09-18 00:42:22Z andreas $
+ * RCSID $Id: vendor.c 4426 2008-10-14 01:53:37Z andreas $
*/
#include <stdlib.h>
@@ -206,7 +206,8 @@ static struct vid_struct _vid_tab[] = {
/*
* strongSwan
*/
- DEC_MD5_VID(STRONGSWAN, "strongSwan 4.2.8")
+ DEC_MD5_VID(STRONGSWAN, "strongSwan 4.2.9")
+ DEC_MD5_VID(STRONGSWAN_4_2_8, "strongSwan 4.2.8")
DEC_MD5_VID(STRONGSWAN_4_2_7, "strongSwan 4.2.7")
DEC_MD5_VID(STRONGSWAN_4_2_6, "strongSwan 4.2.6")
DEC_MD5_VID(STRONGSWAN_4_2_5, "strongSwan 4.2.5")
diff --git a/src/pluto/vendor.h b/src/pluto/vendor.h
index cf6b68e51..819dbd99d 100644
--- a/src/pluto/vendor.h
+++ b/src/pluto/vendor.h
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: vendor.h 4348 2008-09-18 00:42:22Z andreas $
+ * RCSID $Id: vendor.h 4426 2008-10-14 01:53:37Z andreas $
*/
#ifndef _VENDOR_H_
@@ -124,6 +124,7 @@ enum known_vendorid {
VID_STRONGSWAN_4_2_5 =105,
VID_STRONGSWAN_4_2_6 =106,
VID_STRONGSWAN_4_2_7 =107,
+ VID_STRONGSWAN_4_2_8 =108,
/* 101 - 200 : NAT-Traversal */
VID_NATT_STENBERG_01 =151,
diff --git a/src/scepclient/scep.c b/src/scepclient/scep.c
index 0c1265918..1b01044df 100644
--- a/src/scepclient/scep.c
+++ b/src/scepclient/scep.c
@@ -522,7 +522,7 @@ scep_http_request(const char *url, chunk_t pkcs7, scep_op_t op
headers = curl_slist_append(headers, "Content-Type:");
headers = curl_slist_append(headers, "Expect:");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, pkcs7.ptr);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (char*)pkcs7.ptr);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, pkcs7.len);
}
}
diff --git a/src/starter/Makefile.am b/src/starter/Makefile.am
index e6346a585..5ee614f1b 100644
--- a/src/starter/Makefile.am
+++ b/src/starter/Makefile.am
@@ -1,13 +1,13 @@
ipsec_PROGRAMS = starter
starter_SOURCES = y.tab.c netkey.c y.tab.h parser.h args.h netkey.h \
starterwhack.c starterwhack.h starterstroke.c invokepluto.c confread.c \
-starterstroke.h interfaces.c invokepluto.h confread.h interfaces.h args.c \
+starterstroke.h interfaces.c invokepluto.h confread.h interfaces.h args.c \
keywords.c files.h keywords.h cmp.c starter.c cmp.h exec.c invokecharon.c \
-exec.h invokecharon.h lex.yy.c loglite.c
+exec.h invokecharon.h lex.yy.c loglite.c klips.c klips.h
INCLUDES = -I$(top_srcdir)/src/libfreeswan -I$(top_srcdir)/src/pluto -I$(top_srcdir)/src/whack -I$(top_srcdir)/src/stroke
AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" -DIPSEC_CONFDIR=\"${confdir}\" -DIPSEC_PIDDIR=\"${piddir}\" -DIPSEC_EAPDIR=\"${eapdir}\" -DDEBUG
-starter_LDADD = defs.o $(top_srcdir)/src/libfreeswan/libfreeswan.a
+starter_LDADD = defs.o $(top_builddir)/src/libfreeswan/libfreeswan.a
EXTRA_DIST = parser.l parser.y keywords.txt ipsec.conf
dist_man_MANS = ipsec.conf.5 starter.8
MAINTAINERCLEANFILES = lex.yy.c y.tab.c y.tab.h keywords.c
@@ -15,17 +15,17 @@ MAINTAINERCLEANFILES = lex.yy.c y.tab.c y.tab.h keywords.c
PLUTODIR=$(top_srcdir)/src/pluto
SCEPCLIENTDIR=$(top_srcdir)/src/scepclient
-lex.yy.c: y.tab.c parser.l parser.y parser.h
- $(LEX) --nounput parser.l
+lex.yy.c: parser.l parser.y parser.h y.tab.c
+ $(LEX) --nounput $<
-y.tab.c: parser.l parser.y parser.h
- $(YACC) -v -d parser.y
+y.tab.c: parser.y parser.l parser.h
+ $(YACC) -v -d $<
-y.tab.h: parser.l parser.y parser.h
- $(YACC) -v -d parser.y
+y.tab.h: parser.y parser.l parser.h
+ $(YACC) -v -d $<
keywords.c: keywords.txt keywords.h
- $(GPERF) -C -G -t < keywords.txt > keywords.c
+ $(GPERF) -C -G -t < $< > $@
defs.o: $(PLUTODIR)/defs.c $(PLUTODIR)/defs.h
$(COMPILE) -c -o $@ $<
diff --git a/src/starter/Makefile.in b/src/starter/Makefile.in
index 4150a60e7..446edf8c5 100644
--- a/src/starter/Makefile.in
+++ b/src/starter/Makefile.in
@@ -51,10 +51,10 @@ am_starter_OBJECTS = y.tab.$(OBJEXT) netkey.$(OBJEXT) \
invokepluto.$(OBJEXT) confread.$(OBJEXT) interfaces.$(OBJEXT) \
args.$(OBJEXT) keywords.$(OBJEXT) cmp.$(OBJEXT) \
starter.$(OBJEXT) exec.$(OBJEXT) invokecharon.$(OBJEXT) \
- lex.yy.$(OBJEXT) loglite.$(OBJEXT)
+ lex.yy.$(OBJEXT) loglite.$(OBJEXT) klips.$(OBJEXT)
starter_OBJECTS = $(am_starter_OBJECTS)
starter_DEPENDENCIES = defs.o \
- $(top_srcdir)/src/libfreeswan/libfreeswan.a
+ $(top_builddir)/src/libfreeswan/libfreeswan.a
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -214,13 +214,13 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
starter_SOURCES = y.tab.c netkey.c y.tab.h parser.h args.h netkey.h \
starterwhack.c starterwhack.h starterstroke.c invokepluto.c confread.c \
-starterstroke.h interfaces.c invokepluto.h confread.h interfaces.h args.c \
+starterstroke.h interfaces.c invokepluto.h confread.h interfaces.h args.c \
keywords.c files.h keywords.h cmp.c starter.c cmp.h exec.c invokecharon.c \
-exec.h invokecharon.h lex.yy.c loglite.c
+exec.h invokecharon.h lex.yy.c loglite.c klips.c klips.h
INCLUDES = -I$(top_srcdir)/src/libfreeswan -I$(top_srcdir)/src/pluto -I$(top_srcdir)/src/whack -I$(top_srcdir)/src/stroke
AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" -DIPSEC_CONFDIR=\"${confdir}\" -DIPSEC_PIDDIR=\"${piddir}\" -DIPSEC_EAPDIR=\"${eapdir}\" -DDEBUG
-starter_LDADD = defs.o $(top_srcdir)/src/libfreeswan/libfreeswan.a
+starter_LDADD = defs.o $(top_builddir)/src/libfreeswan/libfreeswan.a
EXTRA_DIST = parser.l parser.y keywords.txt ipsec.conf
dist_man_MANS = ipsec.conf.5 starter.8
MAINTAINERCLEANFILES = lex.yy.c y.tab.c y.tab.h keywords.c
@@ -305,6 +305,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/invokecharon.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/invokepluto.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keywords.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/klips.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lex.yy.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loglite.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netkey.Po@am__quote@
@@ -615,17 +616,17 @@ uninstall-man: uninstall-man5 uninstall-man8
uninstall-man8
-lex.yy.c: y.tab.c parser.l parser.y parser.h
- $(LEX) --nounput parser.l
+lex.yy.c: parser.l parser.y parser.h y.tab.c
+ $(LEX) --nounput $<
-y.tab.c: parser.l parser.y parser.h
- $(YACC) -v -d parser.y
+y.tab.c: parser.y parser.l parser.h
+ $(YACC) -v -d $<
-y.tab.h: parser.l parser.y parser.h
- $(YACC) -v -d parser.y
+y.tab.h: parser.y parser.l parser.h
+ $(YACC) -v -d $<
keywords.c: keywords.txt keywords.h
- $(GPERF) -C -G -t < keywords.txt > keywords.c
+ $(GPERF) -C -G -t < $< > $@
defs.o: $(PLUTODIR)/defs.c $(PLUTODIR)/defs.h
$(COMPILE) -c -o $@ $<
diff --git a/src/starter/args.c b/src/starter/args.c
index 7af3b6310..c09bea986 100644
--- a/src/starter/args.c
+++ b/src/starter/args.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: args.c 4276 2008-08-22 10:44:51Z martin $
+ * RCSID $Id: args.c 4612 2008-11-11 06:37:37Z andreas $
*/
#include <stddef.h>
@@ -199,6 +199,7 @@ static const token_info_t token_info[] =
{ ARG_MISC, 0, NULL /* KW_TYPE */ },
{ ARG_MISC, 0, NULL /* KW_PFS */ },
{ ARG_MISC, 0, NULL /* KW_COMPRESS */ },
+ { ARG_ENUM, offsetof(starter_conn_t, install_policy), LST_bool },
{ ARG_MISC, 0, NULL /* KW_AUTH */ },
{ ARG_MISC, 0, NULL /* KW_AUTHBY */ },
{ ARG_MISC, 0, NULL /* KW_EAP */ },
diff --git a/src/starter/confread.c b/src/starter/confread.c
index 959a98b77..1560266c1 100644
--- a/src/starter/confread.c
+++ b/src/starter/confread.c
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: confread.c 4269 2008-08-21 12:10:07Z martin $
+ * RCSID $Id: confread.c 4612 2008-11-11 06:37:37Z andreas $
*/
#include <stddef.h>
@@ -79,6 +79,7 @@ static void default_values(starter_config_t *cfg)
cfg->conn_default.sa_keying_tries = SA_REPLACEMENT_RETRIES_DEFAULT;
cfg->conn_default.addr_family = AF_INET;
cfg->conn_default.tunnel_addr_family = AF_INET;
+ cfg->conn_default.install_policy = TRUE;
cfg->conn_default.dpd_delay = 30; /* seconds */
cfg->conn_default.dpd_timeout = 150; /* seconds */
@@ -497,15 +498,29 @@ load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg)
case KW_TYPE:
conn->policy &= ~(POLICY_TUNNEL | POLICY_SHUNT_MASK);
if (streq(kw->value, "tunnel"))
+ {
conn->policy |= POLICY_TUNNEL;
+ }
else if (streq(kw->value, "beet"))
+ {
conn->policy |= POLICY_BEET;
+ }
+ else if (streq(kw->value, "transport_proxy"))
+ {
+ conn->policy |= POLICY_PROXY;
+ }
else if (streq(kw->value, "passthrough") || streq(kw->value, "pass"))
+ {
conn->policy |= POLICY_SHUNT_PASS;
+ }
else if (streq(kw->value, "drop"))
+ {
conn->policy |= POLICY_SHUNT_DROP;
+ }
else if (streq(kw->value, "reject"))
+ {
conn->policy |= POLICY_SHUNT_REJECT;
+ }
else if (strcmp(kw->value, "transport") != 0)
{
plog("# bad policy value: %s=%s", kw->entry->name, kw->value);
@@ -530,21 +545,33 @@ load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg)
char *second = strchr(kw->value, '|');
if (second != NULL)
+ {
*second = '\0';
+ }
/* also handles the cases secret|rsasig and rsasig|secret */
for (;;)
{
if (streq(value, "rsa") || streq(value, "rsasig"))
+ {
conn->policy |= POLICY_RSASIG | POLICY_ENCRYPT;
+ }
else if (streq(value, "secret") || streq(value, "psk"))
+ {
conn->policy |= POLICY_PSK | POLICY_ENCRYPT;
+ }
else if (streq(value, "ecdsa") || streq(value, "ecdsasig"))
+ {
conn->policy |= POLICY_ECDSASIG | POLICY_ENCRYPT;
+ }
else if (streq(value, "xauthrsasig"))
+ {
conn->policy |= POLICY_XAUTH_RSASIG | POLICY_ENCRYPT;
+ }
else if (streq(value, "xauthpsk"))
+ {
conn->policy |= POLICY_XAUTH_PSK | POLICY_ENCRYPT;
+ }
else
{
plog("# bad policy value: %s=%s", kw->entry->name, kw->value);
@@ -552,7 +579,9 @@ load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg)
break;
}
if (second == NULL)
+ {
break;
+ }
value = second;
second = NULL; /* traverse the loop no more than twice */
}
diff --git a/src/starter/confread.h b/src/starter/confread.h
index 2c6e45984..24a8d073e 100644
--- a/src/starter/confread.h
+++ b/src/starter/confread.h
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: confread.h 4276 2008-08-22 10:44:51Z martin $
+ * RCSID $Id: confread.h 4612 2008-11-11 06:37:37Z andreas $
*/
#ifndef _IPSEC_CONFREAD_H_
@@ -114,7 +114,7 @@ struct starter_conn {
unsigned long sa_rekey_fuzz;
sa_family_t addr_family;
sa_family_t tunnel_addr_family;
-
+ bool install_policy;
starter_end_t left, right;
unsigned long id;
diff --git a/src/starter/files.h b/src/starter/files.h
index b21db8bd1..a40574594 100644
--- a/src/starter/files.h
+++ b/src/starter/files.h
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: files.h 3267 2007-10-08 19:57:54Z andreas $
+ * RCSID $Id: files.h 4618 2008-11-11 09:22:00Z tobias $
*/
#ifndef _STARTER_FILES_H_
@@ -19,7 +19,8 @@
#define STARTER_PID_FILE IPSEC_PIDDIR "/starter.pid"
-#define PROC_NETKEY "/proc/net/pfkey"
+#define PROC_NETKEY "/proc/net/pfkey"
+#define PROC_KLIPS "/proc/net/pf_key"
#define PROC_MODULES "/proc/modules"
#define CONFIG_FILE IPSEC_CONFDIR "/ipsec.conf"
diff --git a/src/starter/invokepluto.c b/src/starter/invokepluto.c
index a3cf3a786..e18d6e38d 100644
--- a/src/starter/invokepluto.c
+++ b/src/starter/invokepluto.c
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: invokepluto.c 3942 2008-05-13 07:37:08Z martin $
+ * RCSID $Id: invokepluto.c 4632 2008-11-11 18:37:19Z martin $
*/
#include <sys/types.h>
@@ -215,7 +215,7 @@ starter_start_pluto (starter_config_t *cfg, bool no_fork)
_stop_requested = 0;
if (cfg->setup.prepluto)
- system(cfg->setup.prepluto);
+ ignore_result(system(cfg->setup.prepluto));
pid = fork();
switch (pid)
@@ -258,7 +258,7 @@ starter_start_pluto (starter_config_t *cfg, bool no_fork)
DBG_log("pluto (%d) started", _pluto_pid)
)
if (cfg->setup.postpluto)
- system(cfg->setup.postpluto);
+ ignore_result(system(cfg->setup.postpluto));
return 0;
}
}
diff --git a/src/starter/ipsec.conf.5 b/src/starter/ipsec.conf.5
index 40ff27d0b..10ce8348e 100644
--- a/src/starter/ipsec.conf.5
+++ b/src/starter/ipsec.conf.5
@@ -1,5 +1,5 @@
.TH IPSEC.CONF 5 "27 Jun 2007"
-.\" RCSID $Id: ipsec.conf.5 4360 2008-09-30 12:36:58Z martin $
+.\" RCSID $Id: ipsec.conf.5 4645 2008-11-13 06:29:53Z andreas $
.SH NAME
ipsec.conf \- IPsec configuration and connections
.SH DESCRIPTION
@@ -397,6 +397,15 @@ may be included, such as
how long the keying channel of a connection ('ISAKMP/IKE SA')
should last before being renegotiated.
.TP
+.B installpolicy
+decides whether IPsec policies are installed in the kernel by the IKEv2
+charon daemon for a given connection. Allows peaceful co-existence e.g. with
+the Mobile IPv6 daemon mip6d who wants to control the kernel policies.
+Acceptable values are
+.B yes
+(the default) and
+.BR no .
+.TP
.B keyexchange
method of key exchange;
which protocol should be used to initialize the connection. Connections marked with
@@ -782,17 +791,20 @@ are
signifying a host-to-host, host-to-subnet, or subnet-to-subnet tunnel;
.BR transport ,
signifying host-to-host transport mode;
+.BR transport_proxy ,
+signifying the special Mobile IPv6 transport proxy mode;
.BR passthrough ,
signifying that no IPsec processing should be done at all;
.BR drop ,
signifying that packets should be discarded; and
.BR reject ,
signifying that packets should be discarded and a diagnostic ICMP returned.
-Charon currently supports only
-.BR tunnel
+Charon currently supports
+.BR tunnel ,
+.BR transport ,
and
-.BR transport
-connection types.
+.BR tunnel_proxy
+connection types, only .
.TP
.B xauth
specifies the role in the XAUTH protocol if activated by
diff --git a/src/starter/keywords.c b/src/starter/keywords.c
index 35c17b9b5..e51780dc1 100644
--- a/src/starter/keywords.c
+++ b/src/starter/keywords.c
@@ -44,7 +44,7 @@ error "gperf generated tables don't work with this execution character set. Plea
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: keywords.txt 4276 2008-08-22 10:44:51Z martin $
+ * RCSID $Id: keywords.txt 4612 2008-11-11 06:37:37Z andreas $
*/
#include <string.h>
@@ -56,7 +56,7 @@ struct kw_entry {
kw_token_t token;
};
-#define TOTAL_KEYWORDS 101
+#define TOTAL_KEYWORDS 102
#define MIN_WORD_LENGTH 3
#define MAX_WORD_LENGTH 17
#define MIN_HASH_VALUE 6
@@ -239,7 +239,8 @@ static const struct kw_entry wordlist[] =
{"pkcs11proxy", KW_PKCS11PROXY},
{""}, {""}, {""}, {""},
{"charondebug", KW_CHARONDEBUG},
- {""}, {""},
+ {""},
+ {"installpolicy", KW_INSTALLPOLICY},
{"cachecrls", KW_CACHECRLS},
{""}, {""}, {""},
{"packetdefault", KW_PACKETDEFAULT},
diff --git a/src/starter/keywords.h b/src/starter/keywords.h
index 1efa5dc2b..756c33075 100644
--- a/src/starter/keywords.h
+++ b/src/starter/keywords.h
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: keywords.h 4276 2008-08-22 10:44:51Z martin $
+ * RCSID $Id: keywords.h 4612 2008-11-11 06:37:37Z andreas $
*/
#ifndef _KEYWORDS_H_
@@ -68,6 +68,7 @@ typedef enum {
KW_TYPE,
KW_PFS,
KW_COMPRESS,
+ KW_INSTALLPOLICY,
KW_AUTH,
KW_AUTHBY,
KW_EAP,
diff --git a/src/starter/keywords.txt b/src/starter/keywords.txt
index 29bd404b5..8dfa03325 100644
--- a/src/starter/keywords.txt
+++ b/src/starter/keywords.txt
@@ -13,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: keywords.txt 4276 2008-08-22 10:44:51Z martin $
+ * RCSID $Id: keywords.txt 4612 2008-11-11 06:37:37Z andreas $
*/
#include <string.h>
@@ -61,6 +61,7 @@ keyexchange, KW_KEYEXCHANGE
type, KW_TYPE
pfs, KW_PFS
compress, KW_COMPRESS
+installpolicy, KW_INSTALLPOLICY
auth, KW_AUTH
authby, KW_AUTHBY
keylife, KW_KEYLIFE
diff --git a/src/starter/klips.c b/src/starter/klips.c
new file mode 100644
index 000000000..5c8164419
--- /dev/null
+++ b/src/starter/klips.c
@@ -0,0 +1,82 @@
+/* strongSwan KLIPS starter
+ * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
+ *
+ * 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.
+ *
+ * RCSID $Id: klips.c 4632 2008-11-11 18:37:19Z martin $
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#include <freeswan.h>
+
+#include "../pluto/constants.h"
+#include "../pluto/defs.h"
+#include "../pluto/log.h"
+
+#include "files.h"
+
+bool
+starter_klips_init(void)
+{
+ struct stat stb;
+
+ if (stat(PROC_KLIPS, &stb) != 0)
+ {
+ /* ipsec module makes the pf_key proc interface visible */
+ if (stat(PROC_MODULES, &stb) == 0)
+ {
+ ignore_result(system("modprobe -qv ipsec"));
+ }
+
+ /* now test again */
+ if (stat(PROC_KLIPS, &stb) != 0)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("kernel appears to lack the KLIPS IPsec stack")
+ )
+ return FALSE;
+ }
+ }
+
+ /* load crypto algorithm modules */
+ ignore_result(system("modprobe -qv ipsec_aes"));
+ ignore_result(system("modprobe -qv ipsec_blowfish"));
+ ignore_result(system("modprobe -qv ipsec_sha2"));
+
+ DBG(DBG_CONTROL,
+ DBG_log("Found KLIPS IPsec stack")
+ )
+
+ return TRUE;
+}
+
+void
+starter_klips_cleanup(void)
+{
+ if (system("type eroute > /dev/null 2>&1") == 0)
+ {
+ ignore_result(system("spi --clear"));
+ ignore_result(system("eroute --clear"));
+ }
+ else if (system("type setkey > /dev/null 2>&1") == 0)
+ {
+ ignore_result(system("setkey -F"));
+ ignore_result(system("setkey -FP"));
+ }
+ else
+ {
+ plog("WARNING: cannot flush IPsec state/policy database");
+ }
+}
+
diff --git a/src/starter/klips.h b/src/starter/klips.h
new file mode 100644
index 000000000..60055b4f1
--- /dev/null
+++ b/src/starter/klips.h
@@ -0,0 +1,24 @@
+/* strongSwan KLIPS initialization and cleanup
+ * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
+ *
+ * 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.
+ *
+ * RCSID $Id: klips.h 4618 2008-11-11 09:22:00Z tobias $
+ */
+
+#ifndef _STARTER_KLIPS_H_
+#define _STARTER_KLIPS_H_
+
+extern bool starter_klips_init (void);
+extern void starter_klips_cleanup (void);
+
+#endif /* _STARTER_KLIPS_H_ */
+
diff --git a/src/starter/lex.yy.c b/src/starter/lex.yy.c
index cd3535318..4b3405eda 100644
--- a/src/starter/lex.yy.c
+++ b/src/starter/lex.yy.c
@@ -500,7 +500,7 @@ char *yytext;
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: parser.l 3267 2007-10-08 19:57:54Z andreas $
+ * RCSID $Id: parser.l 4632 2008-11-11 18:37:19Z martin $
*/
#include <string.h>
@@ -511,6 +511,7 @@ char *yytext;
#define MAX_INCLUDE_DEPTH 20
+#define YY_NO_INPUT
#define YY_NO_UNPUT
extern void yyerror(const char *);
extern int yylex (void);
@@ -617,7 +618,7 @@ int _parser_y_include (const char *filename)
return 0;
}
-#line 621 "lex.yy.c"
+#line 622 "lex.yy.c"
#define INITIAL 0
@@ -771,10 +772,10 @@ YY_DECL
register char *yy_cp, *yy_bp;
register int yy_act;
-#line 134 "parser.l"
+#line 135 "parser.l"
-#line 778 "lex.yy.c"
+#line 779 "lex.yy.c"
if ( !(yy_init) )
{
@@ -859,7 +860,7 @@ do_action: /* This label is used only to access EOF actions. */
goto yy_find_action;
case YY_STATE_EOF(INITIAL):
-#line 136 "parser.l"
+#line 137 "parser.l"
{
if (__parser_y_private.filename[__parser_y_private.stack_ptr]) {
free(__parser_y_private.filename[__parser_y_private.stack_ptr]);
@@ -879,23 +880,23 @@ case YY_STATE_EOF(INITIAL):
YY_BREAK
case 1:
YY_RULE_SETUP
-#line 153 "parser.l"
+#line 154 "parser.l"
return FIRST_SPACES;
YY_BREAK
case 2:
YY_RULE_SETUP
-#line 155 "parser.l"
+#line 156 "parser.l"
/* ignore spaces in line */ ;
YY_BREAK
case 3:
YY_RULE_SETUP
-#line 157 "parser.l"
+#line 158 "parser.l"
return EQUAL;
YY_BREAK
case 4:
/* rule 4 can match eol */
YY_RULE_SETUP
-#line 159 "parser.l"
+#line 160 "parser.l"
{
__parser_y_private.line[__parser_y_private.stack_ptr]++;
return EOL;
@@ -903,37 +904,37 @@ YY_RULE_SETUP
YY_BREAK
case 5:
YY_RULE_SETUP
-#line 164 "parser.l"
+#line 165 "parser.l"
return CONFIG;
YY_BREAK
case 6:
YY_RULE_SETUP
-#line 165 "parser.l"
+#line 166 "parser.l"
return SETUP;
YY_BREAK
case 7:
YY_RULE_SETUP
-#line 166 "parser.l"
+#line 167 "parser.l"
return CONN;
YY_BREAK
case 8:
YY_RULE_SETUP
-#line 167 "parser.l"
+#line 168 "parser.l"
return CA;
YY_BREAK
case 9:
YY_RULE_SETUP
-#line 168 "parser.l"
+#line 169 "parser.l"
return INCLUDE;
YY_BREAK
case 10:
YY_RULE_SETUP
-#line 169 "parser.l"
+#line 170 "parser.l"
return FILE_VERSION;
YY_BREAK
case 11:
YY_RULE_SETUP
-#line 171 "parser.l"
+#line 172 "parser.l"
{
yylval.s = strdup(yytext);
return STRING;
@@ -941,7 +942,7 @@ YY_RULE_SETUP
YY_BREAK
case 12:
YY_RULE_SETUP
-#line 176 "parser.l"
+#line 177 "parser.l"
{
yylval.s = strdup(yytext+1);
if (yylval.s) yylval.s[strlen(yylval.s)-1]='\0';
@@ -950,15 +951,15 @@ YY_RULE_SETUP
YY_BREAK
case 13:
YY_RULE_SETUP
-#line 182 "parser.l"
+#line 183 "parser.l"
yyerror(yytext);
YY_BREAK
case 14:
YY_RULE_SETUP
-#line 184 "parser.l"
+#line 185 "parser.l"
ECHO;
YY_BREAK
-#line 962 "lex.yy.c"
+#line 963 "lex.yy.c"
case YY_END_OF_BUFFER:
{
@@ -1920,7 +1921,7 @@ void yyfree (void * ptr )
#define YYTABLES_NAME "yytables"
-#line 184 "parser.l"
+#line 185 "parser.l"
diff --git a/src/starter/netkey.c b/src/starter/netkey.c
index d3c181456..1490abf29 100644
--- a/src/starter/netkey.c
+++ b/src/starter/netkey.c
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: netkey.c 3267 2007-10-08 19:57:54Z andreas $
+ * RCSID $Id: netkey.c 4632 2008-11-11 18:37:19Z martin $
*/
#include <sys/types.h>
@@ -36,7 +36,7 @@ starter_netkey_init(void)
/* af_key module makes the netkey proc interface visible */
if (stat(PROC_MODULES, &stb) == 0)
{
- system("modprobe -qv af_key");
+ ignore_result(system("modprobe -qv af_key"));
}
/* now test again */
@@ -52,11 +52,11 @@ starter_netkey_init(void)
/* make sure that all required IPsec modules are loaded */
if (stat(PROC_MODULES, &stb) == 0)
{
- system("modprobe -qv ah4");
- system("modprobe -qv esp4");
- system("modprobe -qv ipcomp");
- system("modprobe -qv xfrm4_tunnel");
- system("modprobe -qv xfrm_user");
+ ignore_result(system("modprobe -qv ah4"));
+ ignore_result(system("modprobe -qv esp4"));
+ ignore_result(system("modprobe -qv ipcomp"));
+ ignore_result(system("modprobe -qv xfrm4_tunnel"));
+ ignore_result(system("modprobe -qv xfrm_user"));
}
DBG(DBG_CONTROL,
@@ -70,13 +70,13 @@ starter_netkey_cleanup(void)
{
if (system("ip xfrm state > /dev/null 2>&1") == 0)
{
- system("ip xfrm state flush");
- system("ip xfrm policy flush");
+ ignore_result(system("ip xfrm state flush"));
+ ignore_result(system("ip xfrm policy flush"));
}
else if (system("type setkey > /dev/null 2>&1") == 0)
{
- system("setkey -F");
- system("setkey -FP");
+ ignore_result(system("setkey -F"));
+ ignore_result(system("setkey -FP"));
}
else
{
diff --git a/src/starter/parser.l b/src/starter/parser.l
index 68d3b5556..e51d655df 100644
--- a/src/starter/parser.l
+++ b/src/starter/parser.l
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: parser.l 3267 2007-10-08 19:57:54Z andreas $
+ * RCSID $Id: parser.l 4632 2008-11-11 18:37:19Z martin $
*/
#include <string.h>
@@ -23,6 +23,7 @@
#define MAX_INCLUDE_DEPTH 20
+#define YY_NO_INPUT
#define YY_NO_UNPUT
extern void yyerror(const char *);
extern int yylex (void);
diff --git a/src/starter/starter.c b/src/starter/starter.c
index 61f21d88c..e4ad5286c 100644
--- a/src/starter/starter.c
+++ b/src/starter/starter.c
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: starter.c 4140 2008-07-02 05:51:49Z andreas $
+ * RCSID $Id: starter.c 4632 2008-11-11 18:37:19Z martin $
*/
#include <sys/types.h>
@@ -42,6 +42,7 @@
#include "invokepluto.h"
#include "invokecharon.h"
#include "netkey.h"
+#include "klips.h"
#include "cmp.h"
#include "interfaces.h"
@@ -179,7 +180,7 @@ static void generate_selfcert()
#endif
setegid(gid);
seteuid(uid);
- system("ipsec scepclient --out pkcs1 --out cert-self --quiet");
+ ignore_result(system("ipsec scepclient --out pkcs1 --out cert-self --quiet"));
seteuid(0);
setegid(0);
@@ -194,7 +195,7 @@ static void generate_selfcert()
fprintf(f, ": RSA myKey.der\n");
fclose(f);
}
- chown(SECRETS_FILE, uid, gid);
+ ignore_result(chown(SECRETS_FILE, uid, gid));
umask(oldmask);
}
}
@@ -324,7 +325,11 @@ int main (int argc, char **argv)
if (!starter_netkey_init())
{
plog("no netkey IPSec stack detected");
- exit(LSB_RC_FAILURE);
+ if (!starter_klips_init())
+ {
+ plog("no KLIPS IPSec stack detected");
+ exit(LSB_RC_FAILURE);
+ }
}
last_reload = time(NULL);
diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c
index 4ee73128b..481b7de34 100644
--- a/src/starter/starterstroke.c
+++ b/src/starter/starterstroke.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: starterstroke.c 4276 2008-08-22 10:44:51Z martin $
+ * RCSID $Id: starterstroke.c 4614 2008-11-11 07:28:52Z andreas $
*/
#include <sys/types.h>
@@ -24,6 +24,7 @@
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <linux/xfrm.h>
#include <freeswan.h>
@@ -37,6 +38,9 @@
#include "confread.h"
#include "files.h"
+#define IPV4_LEN 4
+#define IPV6_LEN 16
+
/**
* Authentication methods, must be the same as in charons authenticator.h
*/
@@ -126,7 +130,11 @@ static void ip_address2string(ip_address *addr, char *buffer, size_t len)
case AF_INET:
{
struct sockaddr_in* sin = (struct sockaddr_in*)addr;
- if (inet_ntop(AF_INET, &sin->sin_addr, buffer, len))
+ u_int8_t zeroes[IPV4_LEN];
+
+ memset(zeroes, 0, IPV4_LEN);
+ if (memcmp(zeroes, &(sin->sin_addr.s_addr), IPV4_LEN) &&
+ inet_ntop(AF_INET, &sin->sin_addr, buffer, len))
{
return;
}
@@ -135,7 +143,11 @@ static void ip_address2string(ip_address *addr, char *buffer, size_t len)
case AF_INET6:
{
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr;
- if (inet_ntop(AF_INET6, &sin6->sin6_addr, buffer, len))
+ u_int8_t zeroes[IPV6_LEN];
+
+ memset(zeroes, 0, IPV6_LEN);
+ if (memcmp(zeroes, &(sin6->sin6_addr.s6_addr), IPV6_LEN) &&
+ inet_ntop(AF_INET6, &sin6->sin6_addr, buffer, len))
{
return;
}
@@ -144,8 +156,8 @@ static void ip_address2string(ip_address *addr, char *buffer, size_t len)
default:
break;
}
- /* failed */
- snprintf(buffer, len, "0.0.0.0");
+ /* default */
+ snprintf(buffer, len, "%%any");
}
@@ -231,17 +243,22 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
if (conn->policy & POLICY_TUNNEL)
{
- msg.add_conn.mode = 1; /* XFRM_MODE_TRANSPORT */
+ msg.add_conn.mode = XFRM_MODE_TUNNEL;
}
else if (conn->policy & POLICY_BEET)
{
- msg.add_conn.mode = 4; /* XFRM_MODE_BEET */
+ msg.add_conn.mode = XFRM_MODE_BEET;
}
+ else if (conn->policy & POLICY_PROXY)
+ {
+ msg.add_conn.mode = XFRM_MODE_TRANSPORT;
+ msg.add_conn.proxy_mode = TRUE;
+ }
else
{
- msg.add_conn.mode = 0; /* XFRM_MODE_TUNNEL */
+ msg.add_conn.mode = XFRM_MODE_TRANSPORT;
}
-
+
if (!(conn->policy & POLICY_DONT_REKEY))
{
msg.add_conn.rekey.reauth = (conn->policy & POLICY_DONT_REAUTH) == LEMPTY;
@@ -254,6 +271,7 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
msg.add_conn.mobike = conn->policy & POLICY_MOBIKE;
msg.add_conn.force_encap = conn->policy & POLICY_FORCE_ENCAP;
msg.add_conn.ipcomp = conn->policy & POLICY_COMPRESS;
+ msg.add_conn.install_policy = conn->install_policy;
msg.add_conn.crl_policy = cfg->setup.strictcrlpolicy;
msg.add_conn.unique = cfg->setup.uniqueids;
msg.add_conn.algorithms.ike = push_string(&msg, conn->ike);
diff --git a/src/stroke/Makefile.am b/src/stroke/Makefile.am
index aaedfc787..df20252e2 100644
--- a/src/stroke/Makefile.am
+++ b/src/stroke/Makefile.am
@@ -7,4 +7,4 @@ MAINTAINERCLEANFILES = stroke_keywords.c
AM_CFLAGS = -DIPSEC_PIDDIR=\"${piddir}\"
stroke_keywords.c: stroke_keywords.txt stroke_keywords.h
- $(GPERF) -C -G -t < stroke_keywords.txt > stroke_keywords.c
+ $(GPERF) -C -G -t < $< > $@
diff --git a/src/stroke/Makefile.in b/src/stroke/Makefile.in
index 06d9e07ef..62d1bb83e 100644
--- a/src/stroke/Makefile.in
+++ b/src/stroke/Makefile.in
@@ -488,7 +488,7 @@ uninstall-am: uninstall-ipsecPROGRAMS
stroke_keywords.c: stroke_keywords.txt stroke_keywords.h
- $(GPERF) -C -G -t < stroke_keywords.txt > stroke_keywords.c
+ $(GPERF) -C -G -t < $< > $@
# 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/stroke/stroke_msg.h b/src/stroke/stroke_msg.h
index 4d2fb1071..38f44f923 100644
--- a/src/stroke/stroke_msg.h
+++ b/src/stroke/stroke_msg.h
@@ -19,7 +19,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: stroke_msg.h 4384 2008-10-08 07:00:13Z andreas $
+ * RCSID $Id: stroke_msg.h 4614 2008-11-11 07:28:52Z andreas $
*/
#ifndef STROKE_MSG_H_
@@ -212,6 +212,9 @@ struct stroke_msg_t {
int mobike;
int force_encap;
int ipcomp;
+ int proxy_mode;
+ int install_policy;
+
crl_policy_t crl_policy;
int unique;
struct {
diff --git a/src/whack/whack.c b/src/whack/whack.c
index 5958991f2..a4236a8b4 100644
--- a/src/whack/whack.c
+++ b/src/whack/whack.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: whack.c 3264 2007-10-08 19:49:56Z andreas $
+ * RCSID $Id: whack.c 4632 2008-11-11 18:37:19Z martin $
*/
#include <stdio.h>
@@ -1868,7 +1868,7 @@ main(int argc, char **argv)
}
le++; /* include NL in line */
- write(1, ls, le - ls);
+ ignore_result(write(1, ls, le - ls));
/* figure out prefix number
* and how it should affect our exit status