[Pkg-swan-devel] [strongswan] 01/08: Imported Upstream version 5.4.0

Yves-Alexis Perez corsac at moszumanska.debian.org
Mon Apr 4 11:17:30 UTC 2016


This is an automated email from the git hooks/post-receive script.

corsac pushed a commit to branch master
in repository strongswan.

commit 518dd33c94e041db0444c7d1f33da363bb8e3faf
Author: Yves-Alexis Perez <corsac at debian.org>
Date:   Thu Mar 24 11:59:32 2016 +0100

    Imported Upstream version 5.4.0
---
 Android.common.mk                                  |    2 +-
 Android.mk                                         |    1 -
 Makefile.in                                        |    2 +
 NEWS                                               |   40 +
 conf/Makefile.am                                   |    1 +
 conf/Makefile.in                                   |    3 +
 conf/format-options.py                             |   42 +-
 conf/options/charon.conf                           |    8 +-
 conf/options/charon.opt                            |   13 +-
 conf/plugins/p-cscf.conf                           |   18 +
 conf/plugins/p-cscf.opt                            |   11 +
 conf/strongswan.conf.5.main                        |   24 +-
 config.h.in                                        |    3 +
 configure                                          |  588 +++-
 configure.ac                                       |   74 +-
 init/Makefile.in                                   |    2 +
 init/systemd-swanctl/Makefile.in                   |    2 +
 init/systemd-swanctl/strongswan-swanctl.service.in |    3 +
 init/systemd/Makefile.in                           |    2 +
 man/Makefile.in                                    |    2 +
 man/ipsec.conf.5.in                                |   21 +-
 scripts/Makefile.in                                |    2 +
 src/Makefile.am                                    |    4 -
 src/Makefile.in                                    |   82 +-
 src/_copyright/Makefile.in                         |    2 +
 src/_updown/Makefile.in                            |    2 +
 src/aikgen/Makefile.in                             |    2 +
 src/charon-cmd/Makefile.am                         |    2 -
 src/charon-cmd/Makefile.in                         |    5 +-
 src/charon-cmd/charon-cmd.c                        |    6 -
 src/charon-nm/Makefile.am                          |    2 -
 src/charon-nm/Makefile.in                          |    5 +-
 src/charon-nm/charon-nm.c                          |   11 -
 src/charon-svc/Makefile.am                         |    2 -
 src/charon-svc/Makefile.in                         |    5 +-
 src/charon-svc/charon-svc.c                        |   32 +-
 src/charon-systemd/Makefile.am                     |    6 +-
 src/charon-systemd/Makefile.in                     |   12 +-
 src/charon-systemd/charon-systemd.c                |   16 +-
 src/charon-tkm/Makefile.am                         |    6 +-
 src/charon-tkm/Makefile.in                         |    8 +-
 src/charon-tkm/src/charon-tkm.c                    |   10 -
 src/charon-tkm/src/ees/ees_callbacks.c             |    8 +-
 src/charon-tkm/tests/keymat_tests.c                |    1 -
 src/charon-tkm/tests/tests.c                       |    5 -
 src/charon/Android.mk                              |    3 +-
 src/charon/Makefile.am                             |    2 -
 src/charon/Makefile.in                             |    5 +-
 src/charon/charon.c                                |   11 -
 src/checksum/Makefile.am                           |   10 -
 src/checksum/Makefile.in                           |   79 +-
 src/checksum/checksum_builder.c                    |    7 +-
 src/conftest/Makefile.am                           |    2 -
 src/conftest/Makefile.in                           |    5 +-
 src/conftest/conftest.c                            |    8 -
 src/conftest/conftest.h                            |    1 -
 src/dumm/Makefile.in                               |    2 +
 src/include/Makefile.in                            |    2 +
 src/ipsec/Makefile.in                              |    2 +
 src/ipsec/_ipsec.8                                 |    2 +-
 src/ipsec/_ipsec.in                                |    9 +-
 src/libcharon/Android.mk                           |   20 +-
 src/libcharon/Makefile.am                          |   42 +-
 src/libcharon/Makefile.in                          |  339 ++-
 src/libcharon/attributes/attributes.c              |   16 +-
 src/libcharon/attributes/attributes.h              |    3 +
 src/libcharon/attributes/mem_pool.c                |    1 -
 src/libcharon/bus/listeners/custom_logger.h        |   65 +
 src/libcharon/config/child_cfg.c                   |   54 +-
 src/libcharon/config/child_cfg.h                   |   10 +-
 src/libcharon/config/ike_cfg.c                     |   24 +-
 src/libcharon/config/peer_cfg.c                    |  157 +-
 src/libcharon/config/peer_cfg.h                    |   16 +-
 src/libcharon/config/proposal.c                    |  180 +-
 src/libcharon/daemon.c                             |  278 +-
 src/libcharon/daemon.h                             |   53 +-
 src/libcharon/encoding/message.c                   |   12 +-
 .../encoding/payloads/configuration_attribute.c    |    9 +
 src/libcharon/kernel/kernel_handler.c              |    7 +-
 src/libcharon/kernel/kernel_handler.h              |    2 +-
 src/libcharon/kernel/kernel_interface.c            | 1085 +++++++
 src/libcharon/kernel/kernel_interface.h            |  655 +++++
 src/libcharon/kernel/kernel_ipsec.c                |   36 +
 src/libcharon/kernel/kernel_ipsec.h                |  297 ++
 src/libcharon/kernel/kernel_listener.h             |  107 +
 src/libcharon/kernel/kernel_net.c                  |   36 +
 src/libcharon/kernel/kernel_net.h                  |  196 ++
 src/libcharon/network/receiver.c                   |    6 +-
 src/libcharon/plugins/addrblock/Makefile.am        |    1 -
 src/libcharon/plugins/addrblock/Makefile.in        |    3 +-
 src/libcharon/plugins/android_dns/Makefile.am      |    1 -
 src/libcharon/plugins/android_dns/Makefile.in      |    3 +-
 src/libcharon/plugins/android_log/Makefile.am      |    1 -
 src/libcharon/plugins/android_log/Makefile.in      |    3 +-
 src/libcharon/plugins/attr/Makefile.am             |    1 -
 src/libcharon/plugins/attr/Makefile.in             |    3 +-
 src/libcharon/plugins/attr/attr_provider.c         |   67 +-
 src/libcharon/plugins/attr_sql/Makefile.am         |    1 -
 src/libcharon/plugins/attr_sql/Makefile.in         |    3 +-
 src/libcharon/plugins/certexpire/Makefile.am       |    1 -
 src/libcharon/plugins/certexpire/Makefile.in       |    3 +-
 src/libcharon/plugins/connmark/Makefile.am         |    1 -
 src/libcharon/plugins/connmark/Makefile.in         |    3 +-
 src/libcharon/plugins/connmark/connmark_listener.c |  354 ++-
 src/libcharon/plugins/coupling/Makefile.am         |    1 -
 src/libcharon/plugins/coupling/Makefile.in         |    3 +-
 src/libcharon/plugins/dhcp/Makefile.am             |    1 -
 src/libcharon/plugins/dhcp/Makefile.in             |    3 +-
 src/libcharon/plugins/dhcp/dhcp_socket.c           |    4 +-
 src/libcharon/plugins/dnscert/Makefile.am          |    1 -
 src/libcharon/plugins/dnscert/Makefile.in          |    3 +-
 src/libcharon/plugins/duplicheck/Makefile.am       |    1 -
 src/libcharon/plugins/duplicheck/Makefile.in       |    3 +-
 src/libcharon/plugins/duplicheck/duplicheck.c      |    2 +
 src/libcharon/plugins/eap_aka/Makefile.am          |    1 -
 src/libcharon/plugins/eap_aka/Makefile.in          |    3 +-
 src/libcharon/plugins/eap_aka_3gpp2/Makefile.am    |    1 -
 src/libcharon/plugins/eap_aka_3gpp2/Makefile.in    |    3 +-
 src/libcharon/plugins/eap_dynamic/Makefile.am      |    1 -
 src/libcharon/plugins/eap_dynamic/Makefile.in      |    3 +-
 src/libcharon/plugins/eap_gtc/Makefile.am          |    1 -
 src/libcharon/plugins/eap_gtc/Makefile.in          |    3 +-
 src/libcharon/plugins/eap_identity/Makefile.am     |    1 -
 src/libcharon/plugins/eap_identity/Makefile.in     |    3 +-
 src/libcharon/plugins/eap_md5/Makefile.am          |    1 -
 src/libcharon/plugins/eap_md5/Makefile.in          |    3 +-
 src/libcharon/plugins/eap_mschapv2/Makefile.am     |    1 -
 src/libcharon/plugins/eap_mschapv2/Makefile.in     |    3 +-
 src/libcharon/plugins/eap_peap/Makefile.am         |    1 -
 src/libcharon/plugins/eap_peap/Makefile.in         |    3 +-
 src/libcharon/plugins/eap_radius/Makefile.am       |    1 -
 src/libcharon/plugins/eap_radius/Makefile.in       |    3 +-
 src/libcharon/plugins/eap_sim/Makefile.am          |    1 -
 src/libcharon/plugins/eap_sim/Makefile.in          |    3 +-
 src/libcharon/plugins/eap_sim_file/Makefile.am     |    1 -
 src/libcharon/plugins/eap_sim_file/Makefile.in     |    3 +-
 src/libcharon/plugins/eap_sim_pcsc/Makefile.am     |    1 -
 src/libcharon/plugins/eap_sim_pcsc/Makefile.in     |    3 +-
 .../plugins/eap_simaka_pseudonym/Makefile.am       |    1 -
 .../plugins/eap_simaka_pseudonym/Makefile.in       |    3 +-
 .../plugins/eap_simaka_reauth/Makefile.am          |    1 -
 .../plugins/eap_simaka_reauth/Makefile.in          |    3 +-
 src/libcharon/plugins/eap_simaka_sql/Makefile.am   |    1 -
 src/libcharon/plugins/eap_simaka_sql/Makefile.in   |    3 +-
 src/libcharon/plugins/eap_tls/Makefile.am          |    1 -
 src/libcharon/plugins/eap_tls/Makefile.in          |    3 +-
 src/libcharon/plugins/eap_tnc/Makefile.am          |    1 -
 src/libcharon/plugins/eap_tnc/Makefile.in          |    3 +-
 src/libcharon/plugins/eap_tnc/eap_tnc.c            |    2 +-
 src/libcharon/plugins/eap_ttls/Makefile.am         |    1 -
 src/libcharon/plugins/eap_ttls/Makefile.in         |    3 +-
 src/libcharon/plugins/error_notify/Makefile.am     |    1 -
 src/libcharon/plugins/error_notify/Makefile.in     |    3 +-
 src/libcharon/plugins/ext_auth/Makefile.am         |    1 -
 src/libcharon/plugins/ext_auth/Makefile.in         |    3 +-
 src/libcharon/plugins/farp/Makefile.am             |    1 -
 src/libcharon/plugins/farp/Makefile.in             |    3 +-
 src/libcharon/plugins/forecast/Makefile.am         |    1 -
 src/libcharon/plugins/forecast/Makefile.in         |    3 +-
 .../plugins/forecast/forecast_forwarder.c          |    8 +-
 src/libcharon/plugins/forecast/forecast_listener.c |  252 +-
 src/libcharon/plugins/ha/Makefile.am               |    1 -
 src/libcharon/plugins/ha/Makefile.in               |    3 +-
 src/libcharon/plugins/ha/ha_child.c                |    4 +
 src/libcharon/plugins/ha/ha_dispatcher.c           |   17 +-
 src/libcharon/plugins/ha/ha_ike.c                  |   32 +-
 src/libcharon/plugins/ha/ha_message.c              |    2 +
 src/libcharon/plugins/ha/ha_message.h              |    2 +
 src/libcharon/plugins/ipseckey/Makefile.am         |    1 -
 src/libcharon/plugins/ipseckey/Makefile.in         |    3 +-
 src/libcharon/plugins/kernel_iph/Makefile.am       |    1 -
 src/libcharon/plugins/kernel_iph/Makefile.in       |    3 +-
 src/libcharon/plugins/kernel_iph/kernel_iph_net.c  |    4 +-
 .../plugins/kernel_iph/kernel_iph_plugin.c         |    2 -
 src/libcharon/plugins/kernel_libipsec/Makefile.am  |    1 -
 src/libcharon/plugins/kernel_libipsec/Makefile.in  |    3 +-
 .../kernel_libipsec/kernel_libipsec_ipsec.c        |   63 +-
 .../kernel_libipsec/kernel_libipsec_router.c       |    7 +-
 src/libcharon/plugins/kernel_netlink/Makefile.am   |   44 +
 src/libcharon/plugins/kernel_netlink/Makefile.in   | 1007 +++++++
 .../plugins/kernel_netlink/kernel_netlink_ipsec.c  | 2975 +++++++++++++++++++
 .../plugins/kernel_netlink/kernel_netlink_ipsec.h  |    0
 .../plugins/kernel_netlink/kernel_netlink_net.c    | 2686 +++++++++++++++++
 .../plugins/kernel_netlink/kernel_netlink_net.h    |    0
 .../plugins/kernel_netlink/kernel_netlink_plugin.c |   85 +
 .../plugins/kernel_netlink/kernel_netlink_plugin.h |   42 +
 .../plugins/kernel_netlink/kernel_netlink_shared.c |    0
 .../plugins/kernel_netlink/kernel_netlink_shared.h |  104 +
 .../plugins/kernel_netlink/suites/test_socket.c    |    0
 src/libcharon/plugins/kernel_netlink/tests.c       |   47 +
 .../plugins/kernel_netlink/tests.h                 |    0
 src/libcharon/plugins/kernel_pfkey/Makefile.am     |   19 +
 src/libcharon/plugins/kernel_pfkey/Makefile.in     |  782 +++++
 .../plugins/kernel_pfkey/kernel_pfkey_ipsec.c      | 3094 +++++++++++++++++++
 .../plugins/kernel_pfkey/kernel_pfkey_ipsec.h      |    0
 .../plugins/kernel_pfkey/kernel_pfkey_plugin.c     |   80 +
 .../plugins/kernel_pfkey/kernel_pfkey_plugin.h     |   42 +
 src/libcharon/plugins/kernel_pfroute/Makefile.am   |   19 +
 src/libcharon/plugins/kernel_pfroute/Makefile.in   |  782 +++++
 .../plugins/kernel_pfroute/kernel_pfroute_net.c    | 1902 ++++++++++++
 .../plugins/kernel_pfroute/kernel_pfroute_net.h    |    0
 .../plugins/kernel_pfroute/kernel_pfroute_plugin.c |   74 +
 .../plugins/kernel_pfroute/kernel_pfroute_plugin.h |   42 +
 src/libcharon/plugins/kernel_wfp/Makefile.am       |    1 -
 src/libcharon/plugins/kernel_wfp/Makefile.in       |    3 +-
 .../plugins/kernel_wfp/kernel_wfp_ipsec.c          |   25 +-
 src/libcharon/plugins/led/Makefile.am              |    1 -
 src/libcharon/plugins/led/Makefile.in              |    3 +-
 src/libcharon/plugins/load_tester/Makefile.am      |    1 -
 src/libcharon/plugins/load_tester/Makefile.in      |    3 +-
 .../plugins/load_tester/load_tester_config.c       |   13 +-
 .../plugins/load_tester/load_tester_plugin.c       |   22 +-
 src/libcharon/plugins/lookip/Makefile.am           |    1 -
 src/libcharon/plugins/lookip/Makefile.in           |    3 +-
 src/libcharon/plugins/maemo/Makefile.am            |    1 -
 src/libcharon/plugins/maemo/Makefile.in            |    3 +-
 src/libcharon/plugins/medcli/Makefile.am           |    1 -
 src/libcharon/plugins/medcli/Makefile.in           |    3 +-
 src/libcharon/plugins/medsrv/Makefile.am           |    1 -
 src/libcharon/plugins/medsrv/Makefile.in           |    3 +-
 src/libcharon/plugins/osx_attr/Makefile.am         |    1 -
 src/libcharon/plugins/osx_attr/Makefile.in         |    3 +-
 src/libcharon/plugins/p_cscf/Makefile.am           |   19 +
 src/libcharon/plugins/p_cscf/Makefile.in           |  782 +++++
 src/libcharon/plugins/p_cscf/p_cscf_handler.c      |  173 ++
 src/libcharon/plugins/p_cscf/p_cscf_handler.h      |   49 +
 src/libcharon/plugins/p_cscf/p_cscf_plugin.c       |  101 +
 src/libcharon/plugins/p_cscf/p_cscf_plugin.h       |   43 +
 src/libcharon/plugins/radattr/Makefile.am          |    1 -
 src/libcharon/plugins/radattr/Makefile.in          |    3 +-
 src/libcharon/plugins/resolve/Makefile.am          |    1 -
 src/libcharon/plugins/resolve/Makefile.in          |    3 +-
 src/libcharon/plugins/resolve/resolve_handler.c    |    1 -
 src/libcharon/plugins/smp/Makefile.am              |    1 -
 src/libcharon/plugins/smp/Makefile.in              |    3 +-
 src/libcharon/plugins/smp/smp.c                    |    8 +-
 src/libcharon/plugins/socket_default/Makefile.am   |    1 -
 src/libcharon/plugins/socket_default/Makefile.in   |    3 +-
 .../plugins/socket_default/socket_default_socket.c |    8 +-
 src/libcharon/plugins/socket_dynamic/Makefile.am   |    1 -
 src/libcharon/plugins/socket_dynamic/Makefile.in   |    3 +-
 .../plugins/socket_dynamic/socket_dynamic_socket.c |    7 +-
 src/libcharon/plugins/socket_win/Makefile.am       |    1 -
 src/libcharon/plugins/socket_win/Makefile.in       |    3 +-
 .../plugins/socket_win/socket_win_socket.c         |    7 +-
 src/libcharon/plugins/sql/Makefile.am              |    1 -
 src/libcharon/plugins/sql/Makefile.in              |    3 +-
 src/libcharon/plugins/stroke/Makefile.am           |    1 -
 src/libcharon/plugins/stroke/Makefile.in           |    3 +-
 src/libcharon/plugins/stroke/stroke_config.c       |  123 +-
 src/libcharon/plugins/stroke/stroke_control.c      |    1 -
 src/libcharon/plugins/stroke/stroke_list.c         |  619 +---
 src/libcharon/plugins/stroke/stroke_socket.c       |   13 +-
 src/libcharon/plugins/systime_fix/Makefile.am      |    1 -
 src/libcharon/plugins/systime_fix/Makefile.in      |    3 +-
 src/libcharon/plugins/tnc_ifmap/Makefile.am        |    1 -
 src/libcharon/plugins/tnc_ifmap/Makefile.in        |    3 +-
 .../plugins/tnc_ifmap/tnc_ifmap_listener.c         |    5 +-
 src/libcharon/plugins/tnc_pdp/Makefile.am          |    1 -
 src/libcharon/plugins/tnc_pdp/Makefile.in          |    3 +-
 src/libcharon/plugins/uci/Makefile.am              |    1 -
 src/libcharon/plugins/uci/Makefile.in              |    3 +-
 src/libcharon/plugins/unity/Makefile.am            |    1 -
 src/libcharon/plugins/unity/Makefile.in            |    3 +-
 src/libcharon/plugins/updown/Makefile.am           |    1 -
 src/libcharon/plugins/updown/Makefile.in           |    3 +-
 src/libcharon/plugins/updown/updown_listener.c     |   70 +-
 src/libcharon/plugins/vici/Makefile.am             |    8 +-
 src/libcharon/plugins/vici/Makefile.in             |   22 +-
 src/libcharon/plugins/vici/README.md               |   98 +-
 src/libcharon/plugins/vici/perl/Makefile.am        |   27 +
 src/libcharon/plugins/vici/perl/Makefile.in        |  567 ++++
 .../plugins/vici/perl/Vici-Session/Changes         |    6 +
 .../plugins/vici/perl/Vici-Session/MANIFEST        |    9 +
 .../plugins/vici/perl/Vici-Session/Makefile.PL     |   11 +
 .../plugins/vici/perl/Vici-Session/README.pod      |  649 ++++
 .../vici/perl/Vici-Session/lib/Vici/Message.pm     |  256 ++
 .../vici/perl/Vici-Session/lib/Vici/Packet.pm      |  191 ++
 .../vici/perl/Vici-Session/lib/Vici/Session.pm     |  204 ++
 .../vici/perl/Vici-Session/lib/Vici/Transport.pm   |   88 +
 .../vici/perl/Vici-Session/t/Vici-Session.t        |   18 +
 src/libcharon/plugins/vici/python/Makefile.in      |    2 +
 src/libcharon/plugins/vici/python/vici/session.py  |    8 +
 src/libcharon/plugins/vici/ruby/Makefile.in        |    2 +
 src/libcharon/plugins/vici/ruby/lib/vici.rb        |    6 +
 src/libcharon/plugins/vici/vici_cert_info.c        |   57 +
 src/libcharon/plugins/vici/vici_cert_info.h        |   32 +
 src/libcharon/plugins/vici/vici_config.c           |  359 ++-
 src/libcharon/plugins/vici/vici_config.h           |    5 +-
 src/libcharon/plugins/vici/vici_control.c          |  187 +-
 src/libcharon/plugins/vici/vici_cred.c             |   69 +-
 src/libcharon/plugins/vici/vici_plugin.c           |    3 +-
 src/libcharon/plugins/vici/vici_query.c            |  374 ++-
 src/libcharon/plugins/vici/vici_tests.c            |    1 -
 src/libcharon/plugins/whitelist/Makefile.am        |    1 -
 src/libcharon/plugins/whitelist/Makefile.in        |    3 +-
 src/libcharon/plugins/xauth_eap/Makefile.am        |    1 -
 src/libcharon/plugins/xauth_eap/Makefile.in        |    3 +-
 src/libcharon/plugins/xauth_generic/Makefile.am    |    1 -
 src/libcharon/plugins/xauth_generic/Makefile.in    |    3 +-
 src/libcharon/plugins/xauth_noauth/Makefile.am     |    1 -
 src/libcharon/plugins/xauth_noauth/Makefile.in     |    3 +-
 src/libcharon/plugins/xauth_pam/Makefile.am        |    1 -
 src/libcharon/plugins/xauth_pam/Makefile.in        |    3 +-
 src/libcharon/processing/jobs/adopt_children_job.c |    1 -
 src/libcharon/processing/jobs/redirect_job.c       |  106 +
 src/libcharon/processing/jobs/redirect_job.h       |   51 +
 src/libcharon/processing/jobs/send_keepalive_job.c |    2 +-
 src/libcharon/sa/child_sa.c                        |   82 +-
 src/libcharon/sa/ike_sa.c                          |  557 +++-
 src/libcharon/sa/ike_sa.h                          |   65 +-
 src/libcharon/sa/ike_sa_manager.c                  |   97 +-
 .../ikev1/authenticators/pubkey_v1_authenticator.c |    4 +-
 src/libcharon/sa/ikev1/phase1.c                    |    2 +-
 src/libcharon/sa/ikev1/tasks/isakmp_natd.c         |    3 +-
 src/libcharon/sa/ikev1/tasks/mode_config.c         |   37 +-
 src/libcharon/sa/ikev1/tasks/quick_mode.c          |   18 +-
 src/libcharon/sa/ikev1/tasks/xauth.c               |    1 -
 .../sa/ikev2/authenticators/pubkey_authenticator.c |   23 +-
 src/libcharon/sa/ikev2/task_manager_v2.c           |  102 +-
 src/libcharon/sa/ikev2/tasks/child_create.c        |    7 +-
 src/libcharon/sa/ikev2/tasks/child_rekey.c         |   11 +-
 src/libcharon/sa/ikev2/tasks/ike_auth.c            |  144 +-
 src/libcharon/sa/ikev2/tasks/ike_config.c          |    5 +
 src/libcharon/sa/ikev2/tasks/ike_init.c            |  146 +-
 src/libcharon/sa/ikev2/tasks/ike_me.c              |    5 +-
 src/libcharon/sa/ikev2/tasks/ike_mobike.c          |   13 +-
 src/libcharon/sa/ikev2/tasks/ike_natd.c            |    9 +-
 src/libcharon/sa/ikev2/tasks/ike_redirect.c        |  150 +
 src/libcharon/sa/ikev2/tasks/ike_redirect.h        |   54 +
 src/libcharon/sa/ikev2/tasks/ike_vendor.c          |   56 +-
 .../sa/ikev2/tasks/ike_verify_peer_cert.c          |  117 +
 .../sa/ikev2/tasks/ike_verify_peer_cert.h          |   54 +
 src/libcharon/sa/redirect_manager.c                |  274 ++
 src/libcharon/sa/redirect_manager.h                |  109 +
 src/libcharon/sa/redirect_provider.h               |   59 +
 src/libcharon/sa/shunt_manager.c                   |   25 +-
 src/libcharon/sa/task.c                            |    2 +
 src/libcharon/sa/task.h                            |   18 +-
 src/libcharon/sa/trap_manager.c                    |    4 +-
 src/libcharon/tests/Makefile.am                    |    2 -
 src/libcharon/tests/Makefile.in                    |    5 +-
 src/libcharon/tests/libcharon_tests.c              |    3 -
 src/libfast/Makefile.in                            |    2 +
 src/libhydra/Android.mk                            |   37 -
 src/libhydra/Makefile.am                           |   60 -
 src/libhydra/Makefile.in                           |  922 ------
 src/libhydra/hydra.c                               |   93 -
 src/libhydra/hydra.h                               |   71 -
 src/libhydra/kernel/kernel_interface.c             | 1086 -------
 src/libhydra/kernel/kernel_interface.h             |  655 -----
 src/libhydra/kernel/kernel_ipsec.c                 |   38 -
 src/libhydra/kernel/kernel_ipsec.h                 |  297 --
 src/libhydra/kernel/kernel_listener.h              |  107 -
 src/libhydra/kernel/kernel_net.c                   |   38 -
 src/libhydra/kernel/kernel_net.h                   |  196 --
 src/libhydra/plugins/kernel_netlink/Makefile.am    |   44 -
 src/libhydra/plugins/kernel_netlink/Makefile.in    | 1005 -------
 .../plugins/kernel_netlink/kernel_netlink_ipsec.c  | 2966 -------------------
 .../plugins/kernel_netlink/kernel_netlink_net.c    | 2685 -----------------
 .../plugins/kernel_netlink/kernel_netlink_plugin.c |   87 -
 .../plugins/kernel_netlink/kernel_netlink_plugin.h |   42 -
 .../plugins/kernel_netlink/kernel_netlink_shared.h |   96 -
 src/libhydra/plugins/kernel_netlink/tests.c        |   49 -
 src/libhydra/plugins/kernel_pfkey/Makefile.am      |   19 -
 src/libhydra/plugins/kernel_pfkey/Makefile.in      |  780 -----
 .../plugins/kernel_pfkey/kernel_pfkey_ipsec.c      | 3102 --------------------
 .../plugins/kernel_pfkey/kernel_pfkey_plugin.c     |   82 -
 .../plugins/kernel_pfkey/kernel_pfkey_plugin.h     |   42 -
 src/libhydra/plugins/kernel_pfroute/Makefile.am    |   19 -
 src/libhydra/plugins/kernel_pfroute/Makefile.in    |  780 -----
 .../plugins/kernel_pfroute/kernel_pfroute_net.c    | 1903 ------------
 .../plugins/kernel_pfroute/kernel_pfroute_plugin.c |   76 -
 .../plugins/kernel_pfroute/kernel_pfroute_plugin.h |   42 -
 src/libhydra/tests/Makefile.am                     |   18 -
 src/libhydra/tests/Makefile.in                     |  839 ------
 src/libhydra/tests/hydra_tests.c                   |   53 -
 src/libhydra/tests/hydra_tests.h                   |   14 -
 src/libimcv/Makefile.in                            |    2 +
 src/libimcv/imc/imc_os_info.c                      |   12 +-
 src/libimcv/plugins/imc_attestation/Makefile.in    |    2 +
 src/libimcv/plugins/imc_hcd/Makefile.in            |    2 +
 src/libimcv/plugins/imc_os/Makefile.in             |    2 +
 src/libimcv/plugins/imc_scanner/Makefile.in        |    2 +
 src/libimcv/plugins/imc_swid/Makefile.in           |    2 +
 src/libimcv/plugins/imc_test/Makefile.in           |    2 +
 src/libimcv/plugins/imv_attestation/Makefile.in    |    2 +
 .../imv_attestation/imv_attestation_agent.c        |    6 +-
 .../imv_attestation/imv_attestation_state.h        |    2 +-
 src/libimcv/plugins/imv_hcd/Makefile.in            |    2 +
 src/libimcv/plugins/imv_os/Makefile.in             |    2 +
 src/libimcv/plugins/imv_scanner/Makefile.in        |    2 +
 src/libimcv/plugins/imv_swid/Makefile.in           |    2 +
 src/libimcv/plugins/imv_swid/imv_swid_agent.c      |   11 +-
 src/libimcv/plugins/imv_swid/imv_swid_state.c      |   19 +-
 src/libimcv/plugins/imv_swid/imv_swid_state.h      |   37 +-
 src/libimcv/plugins/imv_test/Makefile.in           |    2 +
 src/libimcv/pts/components/pts_component_manager.h |    4 +-
 src/libipsec/Makefile.in                           |    2 +
 src/libipsec/ipsec_policy_mgr.c                    |   11 +-
 src/libipsec/ipsec_policy_mgr.h                    |   11 +-
 src/libipsec/tests/Makefile.in                     |    2 +
 src/libpttls/Makefile.in                           |    2 +
 src/libradius/Makefile.in                          |    2 +
 src/libsimaka/Makefile.am                          |    1 -
 src/libsimaka/Makefile.in                          |    3 +-
 src/libstrongswan/Android.mk                       |    3 +-
 src/libstrongswan/Makefile.am                      |    4 +-
 src/libstrongswan/Makefile.in                      |   18 +
 src/libstrongswan/asn1/asn1.h                      |    1 +
 src/libstrongswan/asn1/oid.c                       |  889 +++---
 src/libstrongswan/asn1/oid.h                       |  429 +--
 src/libstrongswan/asn1/oid.txt                     |    1 +
 src/libstrongswan/collections/array.c              |   10 +
 src/libstrongswan/collections/array.h              |   15 +
 src/libstrongswan/collections/linked_list.c        |   54 +-
 src/libstrongswan/collections/linked_list.h        |   23 +-
 src/libstrongswan/credentials/auth_cfg.c           |  248 +-
 src/libstrongswan/credentials/auth_cfg.h           |   13 +
 .../credentials/certificates/certificate.c         |    9 +-
 .../credentials/certificates/certificate_printer.c |  753 +++++
 .../credentials/certificates/certificate_printer.h |   70 +
 .../credentials/certificates/ocsp_response.h       |    7 +
 src/libstrongswan/credentials/certificates/x509.c  |   27 +
 src/libstrongswan/credentials/certificates/x509.h  |    4 +
 src/libstrongswan/credentials/credential_manager.c |    8 +-
 src/libstrongswan/credentials/credential_manager.h |    7 +-
 src/libstrongswan/library.c                        |   33 +-
 src/libstrongswan/library.h                        |   12 +-
 src/libstrongswan/plugins/acert/Makefile.in        |    2 +
 src/libstrongswan/plugins/aes/Makefile.in          |    2 +
 src/libstrongswan/plugins/aesni/Makefile.in        |    2 +
 src/libstrongswan/plugins/af_alg/Makefile.in       |    2 +
 src/libstrongswan/plugins/agent/Makefile.in        |    2 +
 src/libstrongswan/plugins/bliss/Makefile.in        |    2 +
 src/libstrongswan/plugins/bliss/tests/Makefile.in  |    2 +
 src/libstrongswan/plugins/blowfish/Makefile.in     |    2 +
 src/libstrongswan/plugins/ccm/Makefile.in          |    2 +
 src/libstrongswan/plugins/chapoly/Makefile.in      |    2 +
 .../plugins/chapoly/chapoly_drv_portable.c         |   21 -
 src/libstrongswan/plugins/cmac/Makefile.in         |    2 +
 src/libstrongswan/plugins/constraints/Makefile.in  |    2 +
 src/libstrongswan/plugins/ctr/Makefile.in          |    2 +
 src/libstrongswan/plugins/curl/Makefile.in         |    2 +
 src/libstrongswan/plugins/des/Makefile.in          |    2 +
 src/libstrongswan/plugins/dnskey/Makefile.in       |    2 +
 src/libstrongswan/plugins/files/Makefile.in        |    2 +
 src/libstrongswan/plugins/fips_prf/Makefile.in     |    2 +
 src/libstrongswan/plugins/gcm/Makefile.in          |    2 +
 src/libstrongswan/plugins/gcrypt/Makefile.in       |    2 +
 src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c   |    8 +-
 src/libstrongswan/plugins/gmp/Makefile.in          |    2 +
 src/libstrongswan/plugins/gmp/gmp_plugin.c         |   16 +-
 src/libstrongswan/plugins/hmac/Makefile.in         |    2 +
 src/libstrongswan/plugins/keychain/Makefile.in     |    2 +
 src/libstrongswan/plugins/ldap/Makefile.in         |    2 +
 src/libstrongswan/plugins/md4/Makefile.in          |    2 +
 src/libstrongswan/plugins/md5/Makefile.in          |    2 +
 src/libstrongswan/plugins/mysql/Makefile.in        |    2 +
 src/libstrongswan/plugins/nonce/Makefile.in        |    2 +
 src/libstrongswan/plugins/ntru/Makefile.in         |    2 +
 src/libstrongswan/plugins/openssl/Makefile.in      |    2 +
 src/libstrongswan/plugins/openssl/openssl_plugin.c |   46 +-
 src/libstrongswan/plugins/padlock/Makefile.in      |    2 +
 src/libstrongswan/plugins/pem/Makefile.in          |    2 +
 src/libstrongswan/plugins/pgp/Makefile.in          |    2 +
 src/libstrongswan/plugins/pkcs1/Makefile.in        |    2 +
 src/libstrongswan/plugins/pkcs11/Makefile.in       |    2 +
 src/libstrongswan/plugins/pkcs12/Makefile.in       |    2 +
 src/libstrongswan/plugins/pkcs7/Makefile.in        |    2 +
 src/libstrongswan/plugins/pkcs8/Makefile.in        |    2 +
 src/libstrongswan/plugins/pubkey/Makefile.in       |    2 +
 src/libstrongswan/plugins/pubkey/pubkey_cert.c     |    8 +
 src/libstrongswan/plugins/pubkey/pubkey_cert.h     |    7 +
 src/libstrongswan/plugins/random/Makefile.in       |    2 +
 src/libstrongswan/plugins/rc2/Makefile.in          |    2 +
 src/libstrongswan/plugins/rdrand/Makefile.in       |    2 +
 src/libstrongswan/plugins/revocation/Makefile.in   |    2 +
 src/libstrongswan/plugins/sha1/Makefile.in         |    2 +
 src/libstrongswan/plugins/sha2/Makefile.in         |    2 +
 src/libstrongswan/plugins/sha3/Makefile.in         |    2 +
 src/libstrongswan/plugins/soup/Makefile.in         |    2 +
 src/libstrongswan/plugins/sqlite/Makefile.in       |    2 +
 src/libstrongswan/plugins/sshkey/Makefile.in       |    2 +
 src/libstrongswan/plugins/test_vectors/Makefile.in |    2 +
 src/libstrongswan/plugins/unbound/Makefile.in      |    2 +
 src/libstrongswan/plugins/winhttp/Makefile.in      |    2 +
 src/libstrongswan/plugins/x509/Makefile.in         |    2 +
 src/libstrongswan/plugins/x509/x509_cert.c         |    4 +-
 .../plugins/x509/x509_ocsp_response.c              |   42 +-
 src/libstrongswan/plugins/xcbc/Makefile.in         |    2 +
 src/libstrongswan/processing/watcher.c             |    7 +
 src/libstrongswan/tests/Makefile.am                |    1 +
 src/libstrongswan/tests/Makefile.in                |   21 +
 src/libstrongswan/tests/suites/test_array.c        |   43 +
 src/libstrongswan/tests/suites/test_auth_cfg.c     |  122 +
 .../tests/suites/test_identification.c             |  261 +-
 src/libstrongswan/tests/suites/test_linked_list.c  |   91 +
 src/libstrongswan/tests/tests.h                    |    1 +
 src/libstrongswan/threading/thread.c               |   34 +-
 src/libstrongswan/threading/thread.h               |    8 +-
 src/libstrongswan/threading/windows/thread.c       |    4 +
 src/libstrongswan/utils/compat/windows.c           |    1 -
 src/libstrongswan/utils/debug.c                    |    6 +-
 src/libstrongswan/utils/identification.c           |  389 ++-
 src/libstrongswan/utils/identification.h           |    2 +
 src/libstrongswan/utils/utils/byteorder.h          |   78 +-
 src/libtls/Makefile.in                             |    2 +
 src/libtls/tests/Makefile.in                       |    2 +
 src/libtls/tls_peer.c                              |    3 +-
 src/libtls/tls_server.c                            |    2 +-
 src/libtnccs/Makefile.in                           |    2 +
 src/libtnccs/plugins/tnc_imc/Makefile.in           |    2 +
 src/libtnccs/plugins/tnc_imv/Makefile.in           |    2 +
 src/libtnccs/plugins/tnc_tnccs/Makefile.in         |    2 +
 src/libtnccs/plugins/tnccs_11/Makefile.in          |    2 +
 src/libtnccs/plugins/tnccs_20/Makefile.in          |    2 +
 src/libtnccs/plugins/tnccs_20/tnccs_20.c           |   38 +-
 src/libtnccs/plugins/tnccs_dynamic/Makefile.in     |    2 +
 src/libtncif/Makefile.in                           |    2 +
 src/manager/Makefile.in                            |    2 +
 src/medsrv/Makefile.in                             |    2 +
 src/pki/Makefile.am                                |    5 +-
 src/pki/Makefile.in                                |   12 +-
 src/pki/command.c                                  |   11 +-
 src/pki/command.h                                  |    2 +-
 src/pki/commands/print.c                           |  543 +---
 src/pki/man/Makefile.in                            |    2 +
 src/pool/Makefile.am                               |    2 -
 src/pool/Makefile.in                               |    5 +-
 src/pt-tls-client/Makefile.in                      |    2 +
 src/scepclient/Makefile.am                         |    1 -
 src/scepclient/Makefile.in                         |    3 +-
 src/starter/Android.mk                             |    3 +-
 src/starter/Makefile.am                            |    4 +-
 src/starter/Makefile.in                            |    8 +-
 src/starter/confread.c                             |    4 +-
 src/starter/netkey.c                               |    1 -
 src/starter/starter.c                              |    4 -
 src/starter/tests/Makefile.in                      |    2 +
 src/stroke/Makefile.in                             |    2 +
 src/stroke/stroke.c                                |   13 +-
 src/swanctl/Makefile.am                            |    8 +-
 src/swanctl/Makefile.in                            |   28 +-
 src/swanctl/command.c                              |   11 +-
 src/swanctl/command.h                              |    4 +-
 src/swanctl/commands/list_algs.c                   |  104 +
 src/swanctl/commands/list_certs.c                  |  603 +---
 src/swanctl/commands/list_sas.c                    |   13 +-
 src/swanctl/commands/load_conns.c                  |    9 +-
 src/swanctl/commands/load_creds.c                  |   47 +-
 src/swanctl/commands/redirect.c                    |  132 +
 src/swanctl/commands/stats.c                       |   12 +
 src/swanctl/swanctl.8.in                           |    9 +-
 src/swanctl/swanctl.conf                           |   22 +-
 src/swanctl/swanctl.conf.5.main                    |  139 +-
 src/swanctl/swanctl.h                              |   18 +
 src/swanctl/swanctl.opt                            |   99 +-
 testing/Makefile.in                                |    2 +
 testing/do-tests                                   |   31 +-
 testing/hosts/alice/etc/ipsec.d/ipsec.sql          |    4 +-
 testing/hosts/bob/etc/ipsec.d/ipsec.sql            |    4 +-
 testing/hosts/carol/etc/ipsec.d/ipsec.sql          |    4 +-
 testing/hosts/dave/etc/ipsec.d/ipsec.sql           |    4 +-
 .../hosts/default/usr/local/bin/expect-connection  |    8 +-
 testing/hosts/moon/etc/ipsec.d/ipsec.sql           |    4 +-
 testing/hosts/sun/etc/ipsec.d/ipsec.sql            |    4 +-
 testing/hosts/venus/etc/ipsec.d/ipsec.sql          |    4 +-
 testing/hosts/winnetou/etc/openssl/generate-crl    |    3 +
 testing/scripts/recipes/013_strongswan.mk          |    1 -
 testing/tests/af-alg/alg-camellia/description.txt  |    5 +-
 testing/tests/af-alg/alg-camellia/evaltest.dat     |    8 +-
 .../af-alg/alg-camellia/hosts/carol/etc/ipsec.conf |   22 -
 .../alg-camellia/hosts/carol/etc/strongswan.conf   |    7 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   27 +
 .../af-alg/alg-camellia/hosts/moon/etc/ipsec.conf  |   21 -
 .../alg-camellia/hosts/moon/etc/strongswan.conf    |    7 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   25 +
 testing/tests/af-alg/alg-camellia/posttest.dat     |    5 +-
 testing/tests/af-alg/alg-camellia/pretest.dat      |    7 +-
 testing/tests/af-alg/alg-camellia/test.conf        |    4 +
 testing/tests/af-alg/rw-cert/description.txt       |    4 +-
 testing/tests/af-alg/rw-cert/evaltest.dat          |   13 +-
 .../af-alg/rw-cert/hosts/carol/etc/ipsec.conf      |   22 -
 .../af-alg/rw-cert/hosts/carol/etc/strongswan.conf |    7 +-
 .../rw-cert/hosts/carol/etc/swanctl/swanctl.conf   |   27 +
 .../tests/af-alg/rw-cert/hosts/dave/etc/ipsec.conf |   22 -
 .../af-alg/rw-cert/hosts/dave/etc/strongswan.conf  |    8 +-
 .../rw-cert/hosts/dave/etc/swanctl/swanctl.conf    |   27 +
 .../tests/af-alg/rw-cert/hosts/moon/etc/ipsec.conf |   21 -
 .../af-alg/rw-cert/hosts/moon/etc/strongswan.conf  |    7 +-
 .../rw-cert/hosts/moon/etc/swanctl/swanctl.conf    |   25 +
 testing/tests/af-alg/rw-cert/posttest.dat          |    8 +-
 testing/tests/af-alg/rw-cert/pretest.dat           |   14 +-
 testing/tests/af-alg/rw-cert/test.conf             |    4 +
 .../tests/gcrypt-ikev2/alg-camellia/evaltest.dat   |    4 +-
 .../alg-camellia/hosts/carol/etc/ipsec.conf        |    2 +-
 .../alg-camellia/hosts/moon/etc/ipsec.conf         |    2 +-
 testing/tests/gcrypt-ikev2/rw-cert/pretest.dat     |    1 +
 testing/tests/ha/active-passive/pretest.dat        |    1 -
 testing/tests/ikev1/alg-3des-md5/evaltest.dat      |    4 +-
 testing/tests/ikev1/alg-sha256/evaltest.dat        |    8 +-
 .../ikev1/alg-sha256/hosts/carol/etc/ipsec.conf    |    4 +-
 .../ikev1/alg-sha256/hosts/moon/etc/ipsec.conf     |    4 +-
 testing/tests/ikev1/alg-sha384/evaltest.dat        |    4 +-
 testing/tests/ikev1/alg-sha512/evaltest.dat        |    4 +-
 .../ip-pool-db/hosts/moon/etc/strongswan.conf      |    2 -
 .../ikev1/xauth-rsa-eap-md5-radius/evaltest.dat    |    2 +-
 testing/tests/ikev1/xauth-rsa-radius/evaltest.dat  |    2 +-
 testing/tests/ikev2/alg-aes-xcbc/evaltest.dat      |    4 +-
 .../ikev2/alg-aes-xcbc/hosts/carol/etc/ipsec.conf  |    4 +-
 .../ikev2/alg-aes-xcbc/hosts/moon/etc/ipsec.conf   |    4 +-
 testing/tests/ikev2/alg-sha256-96/evaltest.dat     |    4 +-
 .../ikev2/alg-sha256-96/hosts/carol/etc/ipsec.conf |    4 +-
 .../ikev2/alg-sha256-96/hosts/moon/etc/ipsec.conf  |    4 +-
 testing/tests/ikev2/alg-sha256/evaltest.dat        |    4 +-
 .../ikev2/alg-sha256/hosts/carol/etc/ipsec.conf    |    4 +-
 .../ikev2/alg-sha256/hosts/moon/etc/ipsec.conf     |    4 +-
 .../ip-pool-db/hosts/moon/etc/strongswan.conf      |    2 -
 .../hosts/moon/etc/strongswan.conf                 |    2 -
 .../ip-two-pools-db/hosts/moon/etc/strongswan.conf |    2 -
 .../hosts/moon/etc/strongswan.conf                 |    2 -
 .../hosts/moon/etc/strongswan.conf                 |    2 -
 testing/tests/ikev2/ip-two-pools/pretest.dat       |    2 +-
 .../tests/ikev2/reauth-mbb-revoked/description.txt |   15 +
 .../tests/ikev2/reauth-mbb-revoked/evaltest.dat    |   10 +
 .../reauth-mbb-revoked/hosts/carol/etc/ipsec.conf  |   21 +
 .../hosts/carol/etc/strongswan.conf                |    7 +
 .../reauth-mbb-revoked/hosts/moon/etc/ipsec.conf   |   19 +
 .../hosts/moon/etc/strongswan.conf                 |    5 +
 .../tests/ikev2/reauth-mbb-revoked/posttest.dat    |    3 +
 testing/tests/ikev2/reauth-mbb-revoked/pretest.dat |    4 +
 .../reauth-mbb-revoked}/test.conf                  |    0
 .../tests/ikev2/redirect-active/description.txt    |    8 +
 testing/tests/ikev2/redirect-active/evaltest.dat   |   28 +
 .../redirect-active/hosts/alice/etc/ipsec.conf     |   19 +
 .../hosts/alice/etc/ipsec.d/certs/marsCert.pem     |   25 +
 .../hosts/alice/etc/ipsec.d/private/marsKey.pem    |   27 +
 .../redirect-active/hosts/alice/etc/ipsec.secrets  |    3 +
 .../redirect-active/hosts/alice/etc/iptables.rules |   34 +
 .../hosts/alice/etc/strongswan.conf                |    6 +
 .../redirect-active/hosts/carol/etc/ipsec.conf     |   19 +
 .../hosts/carol/etc/strongswan.conf                |    5 +
 .../redirect-active/hosts/dave/etc/ipsec.conf      |   19 +
 .../redirect-active/hosts/dave/etc/strongswan.conf |    6 +
 .../redirect-active/hosts/moon/etc/ipsec.conf      |   18 +
 .../hosts/moon/etc/ipsec.d/certs/marsCert.pem      |   25 +
 .../hosts/moon/etc/ipsec.d/private/marsKey.pem     |   27 +
 .../redirect-active/hosts/moon/etc/ipsec.secrets   |    3 +
 .../redirect-active/hosts/moon/etc/strongswan.conf |    6 +
 testing/tests/ikev2/redirect-active/posttest.dat   |   10 +
 testing/tests/ikev2/redirect-active/pretest.dat    |   13 +
 testing/tests/ikev2/redirect-active/test.conf      |   21 +
 testing/tests/ikev2/rw-dnssec/pretest.dat          |    2 +-
 testing/tests/ikev2/trap-any/evaltest.dat          |   10 +-
 testing/tests/libipsec/net2net-null/evaltest.dat   |    4 +-
 .../net2net-null/hosts/moon/etc/ipsec.conf         |    4 +-
 .../libipsec/net2net-null/hosts/sun/etc/ipsec.conf |    4 +-
 .../tests/openssl-ikev1/alg-camellia/evaltest.dat  |   12 +-
 .../alg-camellia/hosts/carol/etc/ipsec.conf        |    4 +-
 .../alg-camellia/hosts/moon/etc/ipsec.conf         |    4 +-
 .../tests/openssl-ikev1/ecdsa-certs/evaltest.dat   |    8 +-
 .../tests/openssl-ikev2/alg-camellia/evaltest.dat  |   12 +-
 .../alg-camellia/hosts/carol/etc/ipsec.conf        |    4 +-
 .../alg-camellia/hosts/moon/etc/ipsec.conf         |    4 +-
 testing/tests/pfkey/alg-aes-xcbc/evaltest.dat      |    4 +-
 .../pfkey/alg-aes-xcbc/hosts/carol/etc/ipsec.conf  |    4 +-
 .../pfkey/alg-aes-xcbc/hosts/moon/etc/ipsec.conf   |    4 +-
 testing/tests/sql/ip-pool-db-expired/evaltest.dat  |   12 +-
 .../hosts/carol/etc/ipsec.d/data.sql               |    2 +-
 .../hosts/carol/etc/strongswan.conf                |    2 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    1 +
 .../hosts/dave/etc/ipsec.d/data.sql                |    2 +-
 .../hosts/dave/etc/strongswan.conf                 |    2 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |    1 +
 .../hosts/moon/etc/ipsec.d/data.sql                |    2 +-
 .../hosts/moon/etc/strongswan.conf                 |    8 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    1 +
 testing/tests/sql/ip-pool-db-expired/posttest.dat  |    8 +-
 testing/tests/sql/ip-pool-db-expired/pretest.dat   |   14 +-
 testing/tests/sql/ip-pool-db-expired/test.conf     |    4 +
 testing/tests/sql/ip-pool-db-restart/evaltest.dat  |   12 +-
 .../hosts/carol/etc/ipsec.d/data.sql               |    2 +-
 .../hosts/carol/etc/strongswan.conf                |    2 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    1 +
 .../hosts/dave/etc/ipsec.d/data.sql                |    2 +-
 .../hosts/dave/etc/strongswan.conf                 |    2 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |    1 +
 .../hosts/moon/etc/ipsec.d/data.sql                |    2 +-
 .../hosts/moon/etc/strongswan.conf                 |    8 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    1 +
 testing/tests/sql/ip-pool-db-restart/posttest.dat  |    8 +-
 testing/tests/sql/ip-pool-db-restart/pretest.dat   |   14 +-
 testing/tests/sql/ip-pool-db-restart/test.conf     |    4 +
 testing/tests/sql/ip-pool-db/evaltest.dat          |   12 +-
 .../ip-pool-db/hosts/carol/etc/ipsec.d/data.sql    |    2 +-
 .../sql/ip-pool-db/hosts/carol/etc/strongswan.conf |    2 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    1 +
 .../sql/ip-pool-db/hosts/dave/etc/ipsec.d/data.sql |    2 +-
 .../sql/ip-pool-db/hosts/dave/etc/strongswan.conf  |    2 +-
 .../ip-pool-db/hosts/dave/etc/swanctl/swanctl.conf |    1 +
 .../sql/ip-pool-db/hosts/moon/etc/ipsec.d/data.sql |    2 +-
 .../sql/ip-pool-db/hosts/moon/etc/strongswan.conf  |    8 +-
 .../ip-pool-db/hosts/moon/etc/swanctl/swanctl.conf |    1 +
 testing/tests/sql/ip-pool-db/posttest.dat          |   11 +-
 testing/tests/sql/ip-pool-db/pretest.dat           |   14 +-
 testing/tests/sql/ip-pool-db/test.conf             |    4 +
 .../sql/ip-split-pools-db-restart/evaltest.dat     |   12 +-
 .../hosts/carol/etc/ipsec.d/data.sql               |    2 +-
 .../hosts/carol/etc/strongswan.conf                |    2 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    1 +
 .../hosts/dave/etc/ipsec.d/data.sql                |    2 +-
 .../hosts/dave/etc/strongswan.conf                 |    2 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |    1 +
 .../hosts/moon/etc/ipsec.d/data.sql                |    2 +-
 .../hosts/moon/etc/strongswan.conf                 |    8 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    1 +
 .../sql/ip-split-pools-db-restart/posttest.dat     |    8 +-
 .../sql/ip-split-pools-db-restart/pretest.dat      |   14 +-
 .../tests/sql/ip-split-pools-db-restart/test.conf  |    4 +
 testing/tests/sql/ip-split-pools-db/evaltest.dat   |   11 +-
 .../hosts/carol/etc/ipsec.d/data.sql               |    2 +-
 .../hosts/carol/etc/strongswan.conf                |    2 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    1 +
 .../hosts/dave/etc/ipsec.d/data.sql                |    2 +-
 .../hosts/dave/etc/strongswan.conf                 |    2 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |    1 +
 .../hosts/moon/etc/ipsec.d/data.sql                |    2 +-
 .../hosts/moon/etc/strongswan.conf                 |    8 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    1 +
 testing/tests/sql/ip-split-pools-db/posttest.dat   |    8 +-
 testing/tests/sql/ip-split-pools-db/pretest.dat    |   14 +-
 testing/tests/sql/ip-split-pools-db/test.conf      |    3 +
 testing/tests/sql/multi-level-ca/evaltest.dat      |   16 +-
 .../hosts/carol/etc/ipsec.d/data.sql               |    2 +-
 .../multi-level-ca/hosts/carol/etc/strongswan.conf |    2 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    1 +
 .../multi-level-ca/hosts/dave/etc/ipsec.d/data.sql |    2 +-
 .../multi-level-ca/hosts/dave/etc/strongswan.conf  |    2 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |    1 +
 .../multi-level-ca/hosts/moon/etc/ipsec.d/data.sql |    2 +-
 .../multi-level-ca/hosts/moon/etc/strongswan.conf  |    2 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    1 +
 testing/tests/sql/multi-level-ca/posttest.dat      |    8 +-
 testing/tests/sql/multi-level-ca/pretest.dat       |   14 +-
 testing/tests/sql/multi-level-ca/test.conf         |    4 +
 testing/tests/sql/net2net-cert/evaltest.dat        |    6 +-
 .../net2net-cert/hosts/moon/etc/ipsec.d/data.sql   |    2 +-
 .../net2net-cert/hosts/moon/etc/strongswan.conf    |    2 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    1 +
 .../net2net-cert/hosts/sun/etc/ipsec.d/data.sql    |    2 +-
 .../sql/net2net-cert/hosts/sun/etc/strongswan.conf |    2 +-
 .../hosts/sun/etc/swanctl/swanctl.conf             |    1 +
 testing/tests/sql/net2net-cert/posttest.dat        |    4 +-
 testing/tests/sql/net2net-cert/pretest.dat         |   11 +-
 testing/tests/sql/net2net-cert/test.conf           |    4 +
 testing/tests/sql/net2net-psk/evaltest.dat         |    6 +-
 .../net2net-psk/hosts/moon/etc/ipsec.d/data.sql    |    2 +-
 .../sql/net2net-psk/hosts/moon/etc/strongswan.conf |    2 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    1 +
 .../sql/net2net-psk/hosts/sun/etc/ipsec.d/data.sql |    2 +-
 .../sql/net2net-psk/hosts/sun/etc/strongswan.conf  |    2 +-
 .../net2net-psk/hosts/sun/etc/swanctl/swanctl.conf |    1 +
 testing/tests/sql/net2net-psk/posttest.dat         |    4 +-
 testing/tests/sql/net2net-psk/pretest.dat          |   11 +-
 testing/tests/sql/net2net-psk/test.conf            |    4 +
 testing/tests/sql/net2net-route-pem/evaltest.dat   |   12 +-
 .../hosts/moon/etc/ipsec.d/data.sql                |    6 +-
 .../hosts/moon/etc/strongswan.conf                 |    2 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    1 +
 .../hosts/sun/etc/ipsec.d/data.sql                 |    6 +-
 .../hosts/sun/etc/strongswan.conf                  |    2 +-
 .../hosts/sun/etc/swanctl/swanctl.conf             |    1 +
 testing/tests/sql/net2net-route-pem/posttest.dat   |    4 +-
 testing/tests/sql/net2net-route-pem/pretest.dat    |   10 +-
 testing/tests/sql/net2net-route-pem/test.conf      |    4 +
 testing/tests/sql/net2net-start-pem/evaltest.dat   |   10 +-
 .../hosts/moon/etc/ipsec.d/data.sql                |   14 +-
 .../hosts/moon/etc/strongswan.conf                 |    2 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    1 +
 .../hosts/sun/etc/ipsec.d/data.sql                 |   14 +-
 .../hosts/sun/etc/strongswan.conf                  |    2 +-
 .../hosts/sun/etc/swanctl/swanctl.conf             |    1 +
 testing/tests/sql/net2net-start-pem/posttest.dat   |    4 +-
 testing/tests/sql/net2net-start-pem/pretest.dat    |   10 +-
 testing/tests/sql/net2net-start-pem/test.conf      |    4 +
 testing/tests/sql/rw-cert/evaltest.dat             |   12 +-
 .../sql/rw-cert/hosts/carol/etc/ipsec.d/data.sql   |    2 +-
 .../sql/rw-cert/hosts/carol/etc/strongswan.conf    |    2 +-
 .../rw-cert/hosts/carol/etc/swanctl/swanctl.conf   |    1 +
 .../sql/rw-cert/hosts/dave/etc/ipsec.d/data.sql    |    2 +-
 .../sql/rw-cert/hosts/dave/etc/strongswan.conf     |    2 +-
 .../rw-cert/hosts/dave/etc/swanctl/swanctl.conf    |    1 +
 .../sql/rw-cert/hosts/moon/etc/ipsec.d/data.sql    |    2 +-
 .../sql/rw-cert/hosts/moon/etc/strongswan.conf     |    2 +-
 .../rw-cert/hosts/moon/etc/swanctl/swanctl.conf    |    1 +
 testing/tests/sql/rw-cert/posttest.dat             |    8 +-
 testing/tests/sql/rw-cert/pretest.dat              |   14 +-
 testing/tests/sql/rw-cert/test.conf                |    4 +
 testing/tests/sql/rw-eap-aka-rsa/evaltest.dat      |    8 +-
 .../hosts/carol/etc/ipsec.d/data.sql               |    2 +-
 .../rw-eap-aka-rsa/hosts/carol/etc/strongswan.conf |    2 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    1 +
 .../rw-eap-aka-rsa/hosts/moon/etc/ipsec.d/data.sql |    2 +-
 .../rw-eap-aka-rsa/hosts/moon/etc/strongswan.conf  |    2 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    1 +
 testing/tests/sql/rw-eap-aka-rsa/posttest.dat      |    5 +-
 testing/tests/sql/rw-eap-aka-rsa/pretest.dat       |    9 +-
 testing/tests/sql/rw-eap-aka-rsa/test.conf         |    4 +
 testing/tests/sql/rw-psk-ipv4/evaltest.dat         |   13 +-
 .../rw-psk-ipv4/hosts/carol/etc/ipsec.d/data.sql   |    2 +-
 .../rw-psk-ipv4/hosts/carol/etc/strongswan.conf    |    2 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    1 +
 .../rw-psk-ipv4/hosts/dave/etc/ipsec.d/data.sql    |    2 +-
 .../sql/rw-psk-ipv4/hosts/dave/etc/strongswan.conf |    2 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |    1 +
 .../rw-psk-ipv4/hosts/moon/etc/ipsec.d/data.sql    |    2 +-
 .../sql/rw-psk-ipv4/hosts/moon/etc/strongswan.conf |    2 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    1 +
 testing/tests/sql/rw-psk-ipv4/posttest.dat         |    8 +-
 testing/tests/sql/rw-psk-ipv4/pretest.dat          |   14 +-
 testing/tests/sql/rw-psk-ipv4/test.conf            |    4 +
 testing/tests/sql/rw-psk-ipv6/evaltest.dat         |   13 +-
 .../rw-psk-ipv6/hosts/carol/etc/ipsec.d/data.sql   |    2 +-
 .../rw-psk-ipv6/hosts/carol/etc/strongswan.conf    |    2 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    1 +
 .../rw-psk-ipv6/hosts/dave/etc/ipsec.d/data.sql    |    2 +-
 .../sql/rw-psk-ipv6/hosts/dave/etc/strongswan.conf |    2 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |    1 +
 .../rw-psk-ipv6/hosts/moon/etc/ipsec.d/data.sql    |    2 +-
 .../sql/rw-psk-ipv6/hosts/moon/etc/strongswan.conf |    2 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    1 +
 testing/tests/sql/rw-psk-ipv6/posttest.dat         |    8 +-
 testing/tests/sql/rw-psk-ipv6/pretest.dat          |   14 +-
 testing/tests/sql/rw-psk-ipv6/test.conf            |    6 +-
 testing/tests/sql/rw-psk-rsa-split/evaltest.dat    |   12 +-
 .../hosts/carol/etc/ipsec.d/data.sql               |    2 +-
 .../hosts/carol/etc/strongswan.conf                |    2 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    1 +
 .../hosts/dave/etc/ipsec.d/data.sql                |    2 +-
 .../hosts/dave/etc/strongswan.conf                 |    2 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |    1 +
 .../hosts/moon/etc/ipsec.d/data.sql                |    2 +-
 .../hosts/moon/etc/strongswan.conf                 |    2 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    1 +
 testing/tests/sql/rw-psk-rsa-split/posttest.dat    |    8 +-
 testing/tests/sql/rw-psk-rsa-split/pretest.dat     |   14 +-
 testing/tests/sql/rw-psk-rsa-split/test.conf       |    4 +
 testing/tests/sql/rw-rsa-keyid/evaltest.dat        |   12 +-
 .../rw-rsa-keyid/hosts/carol/etc/ipsec.d/data.sql  |    2 +-
 .../rw-rsa-keyid/hosts/carol/etc/strongswan.conf   |    2 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    1 +
 .../rw-rsa-keyid/hosts/dave/etc/ipsec.d/data.sql   |    2 +-
 .../rw-rsa-keyid/hosts/dave/etc/strongswan.conf    |    2 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |    1 +
 .../rw-rsa-keyid/hosts/moon/etc/ipsec.d/data.sql   |    2 +-
 .../rw-rsa-keyid/hosts/moon/etc/strongswan.conf    |    2 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    1 +
 testing/tests/sql/rw-rsa-keyid/posttest.dat        |    8 +-
 testing/tests/sql/rw-rsa-keyid/pretest.dat         |   14 +-
 testing/tests/sql/rw-rsa-keyid/test.conf           |    4 +
 testing/tests/sql/rw-rsa/evaltest.dat              |   12 +-
 .../sql/rw-rsa/hosts/carol/etc/ipsec.d/data.sql    |    2 +-
 .../sql/rw-rsa/hosts/carol/etc/strongswan.conf     |    2 +-
 .../rw-rsa/hosts/carol/etc/swanctl/swanctl.conf    |    1 +
 .../sql/rw-rsa/hosts/dave/etc/ipsec.d/data.sql     |    2 +-
 .../sql/rw-rsa/hosts/dave/etc/strongswan.conf      |    2 +-
 .../sql/rw-rsa/hosts/dave/etc/swanctl/swanctl.conf |    1 +
 .../sql/rw-rsa/hosts/moon/etc/ipsec.d/data.sql     |    2 +-
 .../sql/rw-rsa/hosts/moon/etc/strongswan.conf      |    2 +-
 .../sql/rw-rsa/hosts/moon/etc/swanctl/swanctl.conf |    1 +
 testing/tests/sql/rw-rsa/posttest.dat              |    8 +-
 testing/tests/sql/rw-rsa/pretest.dat               |   14 +-
 testing/tests/sql/rw-rsa/test.conf                 |    4 +
 .../tests/sql/shunt-policies-nat-rw/evaltest.dat   |   13 +-
 .../hosts/alice/etc/ipsec.conf                     |    3 -
 .../hosts/alice/etc/ipsec.secrets                  |    3 -
 .../hosts/alice/etc/strongswan.conf                |    2 +-
 .../hosts/alice/etc/swanctl/swanctl.conf           |    1 +
 .../shunt-policies-nat-rw/hosts/sun/etc/ipsec.conf |    3 -
 .../hosts/sun/etc/ipsec.d/data.sql                 |    2 +-
 .../hosts/sun/etc/ipsec.secrets                    |    3 -
 .../hosts/sun/etc/strongswan.conf                  |    2 +-
 .../hosts/sun/etc/swanctl/swanctl.conf             |    1 +
 .../hosts/venus/etc/ipsec.conf                     |    3 -
 .../hosts/venus/etc/ipsec.secrets                  |    3 -
 .../hosts/venus/etc/strongswan.conf                |    2 +-
 .../hosts/venus/etc/swanctl/swanctl.conf           |    1 +
 .../tests/sql/shunt-policies-nat-rw/posttest.dat   |    8 +-
 .../tests/sql/shunt-policies-nat-rw/pretest.dat    |   15 +-
 testing/tests/sql/shunt-policies-nat-rw/test.conf  |    4 +
 .../tests/swanctl/config-payload/description.txt   |    8 +
 testing/tests/swanctl/config-payload/evaltest.dat  |   16 +
 .../config-payload/hosts/carol/etc/strongswan.conf |   14 +
 .../hosts/carol/etc/swanctl/swanctl.conf           |   28 +
 .../config-payload/hosts/dave/etc/strongswan.conf  |   14 +
 .../hosts/dave/etc/swanctl/swanctl.conf            |   28 +
 .../config-payload/hosts/moon/etc/strongswan.conf  |   15 +
 .../hosts/moon/etc/swanctl/swanctl.conf            |   34 +
 .../hosts/moon/etc/swanctl/swanctl_base.conf       |   17 +
 testing/tests/swanctl/config-payload/posttest.dat  |    8 +
 testing/tests/swanctl/config-payload/pretest.dat   |   12 +
 testing/tests/swanctl/config-payload/test.conf     |   25 +
 testing/tests/swanctl/dhcp-dynamic/description.txt |    8 +
 testing/tests/swanctl/dhcp-dynamic/evaltest.dat    |   22 +
 .../dhcp-dynamic/hosts/carol/etc/strongswan.conf   |   14 +
 .../hosts/carol/etc/swanctl/swanctl.conf           |   28 +
 .../dhcp-dynamic/hosts/dave/etc/strongswan.conf    |   14 +
 .../hosts/dave/etc/swanctl/swanctl.conf            |   28 +
 .../swanctl/dhcp-dynamic/hosts/moon/etc/dhcpd.conf |    9 +
 .../dhcp-dynamic/hosts/moon/etc/iptables.rules     |   39 +
 .../dhcp-dynamic/hosts/moon/etc/strongswan.conf    |   20 +
 .../hosts/moon/etc/swanctl/swanctl.conf            |   26 +
 .../dhcp-dynamic/hosts/venus/etc/dhcp/dhcpd.conf   |   14 +
 .../dhcp-dynamic/hosts/venus/etc/dnsmasq.conf      |    7 +
 testing/tests/swanctl/dhcp-dynamic/posttest.dat    |   12 +
 testing/tests/swanctl/dhcp-dynamic/pretest.dat     |   13 +
 testing/tests/swanctl/dhcp-dynamic/test.conf       |   25 +
 testing/tests/swanctl/frags-ipv4/description.txt   |    8 +-
 testing/tests/swanctl/frags-ipv4/evaltest.dat      |    8 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    5 -
 .../frags-ipv4/hosts/dave/etc/swanctl/swanctl.conf |    5 -
 .../frags-ipv4/hosts/moon/etc/swanctl/swanctl.conf |    5 -
 testing/tests/swanctl/frags-ipv4/pretest.dat       |    4 +-
 testing/tests/swanctl/frags-ipv6/evaltest.dat      |    8 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    5 -
 .../frags-ipv6/hosts/dave/etc/swanctl/swanctl.conf |    5 -
 .../frags-ipv6/hosts/moon/etc/swanctl/swanctl.conf |    5 -
 testing/tests/swanctl/frags-ipv6/pretest.dat       |    4 +-
 testing/tests/swanctl/ip-pool-db/evaltest.dat      |    8 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    9 +-
 .../ip-pool-db/hosts/dave/etc/swanctl/swanctl.conf |    9 +-
 .../ip-pool-db/hosts/moon/etc/swanctl/swanctl.conf |    9 +-
 testing/tests/swanctl/ip-pool-db/pretest.dat       |    6 +-
 testing/tests/swanctl/ip-pool/evaltest.dat         |    8 +-
 .../ip-pool/hosts/carol/etc/swanctl/swanctl.conf   |    9 +-
 .../ip-pool/hosts/dave/etc/swanctl/swanctl.conf    |    9 +-
 .../ip-pool/hosts/moon/etc/swanctl/swanctl.conf    |    9 +-
 testing/tests/swanctl/ip-pool/pretest.dat          |    4 +-
 .../mult-auth-rsa-eap-sim-id/description.txt       |   17 +
 .../swanctl/mult-auth-rsa-eap-sim-id/evaltest.dat  |   20 +
 .../hosts/alice/etc/freeradius/eap.conf            |    5 +
 .../hosts/alice/etc/freeradius/modules/sim_files   |    3 +
 .../hosts/alice/etc/freeradius/proxy.conf          |    5 +
 .../alice/etc/freeradius/sites-available/default   |   61 +
 .../hosts/alice/etc/freeradius/triplets.dat        |    6 +
 .../hosts/alice/etc/freeradius/users               |    0
 .../hosts/carol/etc/ipsec.d/triplets.dat           |    3 +
 .../hosts/carol/etc/strongswan.conf                |   10 +
 .../hosts/carol/etc/swanctl/swanctl.conf           |   32 +
 .../hosts/dave/etc/ipsec.d/triplets.dat            |    3 +
 .../hosts/dave/etc/strongswan.conf                 |   10 +
 .../hosts/dave/etc/swanctl/swanctl.conf            |   32 +
 .../hosts/moon/etc/iptables.rules                  |    0
 .../hosts/moon/etc/strongswan.conf                 |   17 +
 .../hosts/moon/etc/swanctl/swanctl.conf            |   30 +
 .../swanctl/mult-auth-rsa-eap-sim-id/posttest.dat  |    4 +
 .../swanctl/mult-auth-rsa-eap-sim-id/pretest.dat   |   15 +
 .../swanctl/mult-auth-rsa-eap-sim-id/test.conf     |   30 +
 testing/tests/swanctl/multi-level-ca/evaltest.dat  |   12 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    1 -
 .../hosts/dave/etc/swanctl/swanctl.conf            |    1 -
 .../hosts/moon/etc/swanctl/swanctl.conf            |    2 -
 testing/tests/swanctl/multi-level-ca/pretest.dat   |    4 +-
 testing/tests/swanctl/net2net-cert/evaltest.dat    |    4 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    9 +-
 .../hosts/sun/etc/swanctl/swanctl.conf             |    9 +-
 testing/tests/swanctl/net2net-cert/pretest.dat     |    3 +-
 .../tests/swanctl/net2net-pubkey/description.txt   |    7 +
 testing/tests/swanctl/net2net-pubkey/evaltest.dat  |    5 +
 .../net2net-pubkey/hosts/moon/etc/strongswan.conf  |   10 +
 .../hosts/moon/etc/swanctl/pubkey/moonPub.pem      |    9 +
 .../hosts/moon/etc/swanctl/pubkey/sunPub.pem       |    9 +
 .../hosts/moon/etc/swanctl/swanctl.conf            |   30 +
 .../net2net-pubkey/hosts/sun/etc/strongswan.conf   |   10 +
 .../hosts/sun/etc/swanctl/pubkey/moonPub.pem       |    9 +
 .../hosts/sun/etc/swanctl/pubkey/sunPub.pem        |    9 +
 .../hosts/sun/etc/swanctl/swanctl.conf             |   30 +
 testing/tests/swanctl/net2net-pubkey/posttest.dat  |    7 +
 testing/tests/swanctl/net2net-pubkey/pretest.dat   |    8 +
 testing/tests/swanctl/net2net-pubkey/test.conf     |   25 +
 testing/tests/swanctl/net2net-route/evaltest.dat   |    4 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    8 +-
 .../hosts/sun/etc/swanctl/swanctl.conf             |    8 +-
 testing/tests/swanctl/net2net-route/pretest.dat    |    5 +-
 testing/tests/swanctl/net2net-start/evaltest.dat   |    4 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    8 +-
 .../hosts/sun/etc/swanctl/swanctl.conf             |    8 +-
 testing/tests/swanctl/net2net-start/pretest.dat    |    2 +-
 .../tests/swanctl/ocsp-multi-level/evaltest.dat    |   22 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    1 -
 .../hosts/dave/etc/swanctl/swanctl.conf            |    1 -
 .../hosts/moon/etc/swanctl/swanctl.conf            |    2 -
 testing/tests/swanctl/ocsp-multi-level/pretest.dat |    4 +-
 .../tests/swanctl/protoport-dual/description.txt   |    7 +
 testing/tests/swanctl/protoport-dual/evaltest.dat  |    7 +
 .../protoport-dual/hosts/carol/etc/strongswan.conf |   10 +
 .../hosts/carol/etc/swanctl/swanctl.conf           |   35 +
 .../protoport-dual/hosts/moon/etc/strongswan.conf  |   10 +
 .../hosts/moon/etc/swanctl/swanctl.conf            |   35 +
 testing/tests/swanctl/protoport-dual/posttest.dat  |    5 +
 testing/tests/swanctl/protoport-dual/pretest.dat   |    8 +
 testing/tests/swanctl/protoport-dual/test.conf     |   25 +
 .../tests/swanctl/protoport-range/description.txt  |    7 +
 testing/tests/swanctl/protoport-range/evaltest.dat |    7 +
 .../hosts/carol/etc/strongswan.conf                |   10 +
 .../hosts/carol/etc/swanctl/swanctl.conf           |   42 +
 .../protoport-range/hosts/moon/etc/strongswan.conf |   10 +
 .../hosts/moon/etc/swanctl/swanctl.conf            |   43 +
 testing/tests/swanctl/protoport-range/posttest.dat |    5 +
 testing/tests/swanctl/protoport-range/pretest.dat  |   10 +
 testing/tests/swanctl/protoport-range/test.conf    |   25 +
 testing/tests/swanctl/rw-cert/evaltest.dat         |    8 +-
 .../hosts/carol/etc/swanctl/rsa/carolKey.pem       |   30 +
 .../rw-cert/hosts/carol/etc/swanctl/swanctl.conf   |   17 +-
 .../rw-cert/hosts/dave/etc/swanctl/swanctl.conf    |    9 +-
 .../rw-cert/hosts/moon/etc/swanctl/swanctl.conf    |    9 +-
 testing/tests/swanctl/rw-cert/pretest.dat          |    4 +-
 testing/tests/swanctl/rw-dnssec/description.txt    |   10 +
 testing/tests/swanctl/rw-dnssec/evaltest.dat       |   20 +
 .../rw-dnssec/hosts/carol/etc/iptables.rules       |   28 +
 .../swanctl/rw-dnssec/hosts/carol/etc/resolv.conf  |    1 +
 .../rw-dnssec/hosts/carol/etc/strongswan.conf      |   19 +
 .../rw-dnssec/hosts/carol/etc/swanctl/dnssec.keys  |   10 +
 .../hosts/carol/etc/swanctl/pubkey/carolPub.der    |  Bin 0 -> 294 bytes
 .../rw-dnssec/hosts/carol/etc/swanctl/swanctl.conf |   28 +
 .../rw-dnssec/hosts/dave/etc/iptables.rules        |   28 +
 .../swanctl/rw-dnssec/hosts/dave/etc/resolv.conf   |    1 +
 .../rw-dnssec/hosts/dave/etc/strongswan.conf       |   19 +
 .../rw-dnssec/hosts/dave/etc/swanctl/dnssec.keys   |   10 +
 .../hosts/dave/etc/swanctl/pubkey/davePub.der      |  Bin 0 -> 294 bytes
 .../rw-dnssec/hosts/dave/etc/swanctl/swanctl.conf  |   28 +
 .../rw-dnssec/hosts/moon/etc/iptables.rules        |   28 +
 .../swanctl/rw-dnssec/hosts/moon/etc/resolv.conf   |    1 +
 .../rw-dnssec/hosts/moon/etc/strongswan.conf       |   22 +
 .../rw-dnssec/hosts/moon/etc/swanctl/dnssec.keys   |   10 +
 .../hosts/moon/etc/swanctl/pubkey/moonPub.der      |  Bin 0 -> 294 bytes
 .../rw-dnssec/hosts/moon/etc/swanctl/swanctl.conf  |   32 +
 testing/tests/swanctl/rw-dnssec/posttest.dat       |   11 +
 testing/tests/swanctl/rw-dnssec/pretest.dat        |   14 +
 testing/tests/swanctl/rw-dnssec/test.conf          |   25 +
 testing/tests/swanctl/rw-hash-and-url/evaltest.dat |    8 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    9 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |    9 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    9 +-
 testing/tests/swanctl/rw-hash-and-url/pretest.dat  |    4 +-
 .../tests/swanctl/rw-ntru-bliss/description.txt    |   14 +
 testing/tests/swanctl/rw-ntru-bliss/evaltest.dat   |   18 +
 .../rw-ntru-bliss/hosts/carol/etc/strongswan.conf  |   13 +
 .../hosts/carol/etc/swanctl/bliss/carolKey.der     |  Bin 0 -> 1182 bytes
 .../hosts/carol/etc/swanctl/swanctl.conf           |   30 +
 .../hosts/carol/etc/swanctl/x509/carolCert.der     |  Bin 0 -> 2175 bytes
 .../etc/swanctl/x509ca/strongswan_blissCert.der    |  Bin 0 -> 2086 bytes
 .../rw-ntru-bliss/hosts/dave/etc/strongswan.conf   |   13 +
 .../hosts/dave/etc/swanctl/bliss/daveKey.der       |  Bin 0 -> 1310 bytes
 .../hosts/dave/etc/swanctl/swanctl.conf            |   30 +
 .../hosts/dave/etc/swanctl/x509/daveCert.der       |  Bin 0 -> 2179 bytes
 .../etc/swanctl/x509ca/strongswan_blissCert.der    |  Bin 0 -> 2086 bytes
 .../rw-ntru-bliss/hosts/moon/etc/strongswan.conf   |   14 +
 .../hosts/moon/etc/swanctl/bliss/moonKey.der       |  Bin 0 -> 1310 bytes
 .../hosts/moon/etc/swanctl/swanctl.conf            |   34 +
 .../hosts/moon/etc/swanctl/x509/moonCert.der       |  Bin 0 -> 2200 bytes
 .../etc/swanctl/x509ca/strongswan_blissCert.der    |  Bin 0 -> 2086 bytes
 testing/tests/swanctl/rw-ntru-bliss/posttest.dat   |    9 +
 testing/tests/swanctl/rw-ntru-bliss/pretest.dat    |   14 +
 testing/tests/swanctl/rw-ntru-bliss/test.conf      |   25 +
 testing/tests/swanctl/rw-psk-fqdn/evaltest.dat     |    8 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    9 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |    9 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    9 +-
 testing/tests/swanctl/rw-psk-fqdn/pretest.dat      |    4 +-
 testing/tests/swanctl/rw-psk-ikev1/description.txt |   16 +
 testing/tests/swanctl/rw-psk-ikev1/evaltest.dat    |   14 +
 .../rw-psk-ikev1/hosts/carol/etc/strongswan.conf   |   23 +
 .../hosts/carol/etc/swanctl/swanctl.conf           |   33 +
 .../rw-psk-ikev1/hosts/dave/etc/strongswan.conf    |   23 +
 .../hosts/dave/etc/swanctl/swanctl.conf            |   32 +
 .../rw-psk-ikev1/hosts/moon/etc/strongswan.conf    |   23 +
 .../hosts/moon/etc/swanctl/swanctl.conf            |   67 +
 testing/tests/swanctl/rw-psk-ikev1/posttest.dat    |    8 +
 testing/tests/swanctl/rw-psk-ikev1/pretest.dat     |   15 +
 testing/tests/swanctl/rw-psk-ikev1/test.conf       |   25 +
 testing/tests/swanctl/rw-psk-ipv4/evaltest.dat     |    8 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    9 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |    9 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    9 +-
 testing/tests/swanctl/rw-psk-ipv4/pretest.dat      |    4 +-
 .../tests/swanctl/rw-pubkey-anon/description.txt   |    9 +
 testing/tests/swanctl/rw-pubkey-anon/evaltest.dat  |   10 +
 .../rw-pubkey-anon/hosts/carol/etc/strongswan.conf |   14 +
 .../hosts/carol/etc/swanctl/pubkey/carolPub.pem    |    9 +
 .../hosts/carol/etc/swanctl/pubkey/moonPub.pem     |    9 +
 .../hosts/carol/etc/swanctl/rsa/carolKey.pem       |   30 +
 .../hosts/carol/etc/swanctl/swanctl.conf           |   34 +
 .../rw-pubkey-anon/hosts/dave/etc/strongswan.conf  |   14 +
 .../hosts/dave/etc/swanctl/pubkey/davePub.pem      |    9 +
 .../hosts/dave/etc/swanctl/pubkey/moonPub.pem      |    9 +
 .../hosts/dave/etc/swanctl/swanctl.conf            |   26 +
 .../rw-pubkey-anon/hosts/moon/etc/strongswan.conf  |   14 +
 .../hosts/moon/etc/swanctl/pubkey/carolPub.pem     |    9 +
 .../hosts/moon/etc/swanctl/pubkey/davePub.pem      |    9 +
 .../hosts/moon/etc/swanctl/pubkey/moonPub.pem      |    9 +
 .../hosts/moon/etc/swanctl/pubkey/sunPub.pem       |    9 +
 .../hosts/moon/etc/swanctl/swanctl.conf            |   24 +
 testing/tests/swanctl/rw-pubkey-anon/posttest.dat  |   11 +
 testing/tests/swanctl/rw-pubkey-anon/pretest.dat   |   14 +
 testing/tests/swanctl/rw-pubkey-anon/test.conf     |   25 +
 .../tests/swanctl/rw-pubkey-keyid/description.txt  |    8 +
 testing/tests/swanctl/rw-pubkey-keyid/evaltest.dat |   10 +
 .../hosts/carol/etc/strongswan.conf                |   14 +
 .../hosts/carol/etc/swanctl/pubkey/carolPub.pem    |    9 +
 .../hosts/carol/etc/swanctl/pubkey/moonPub.pem     |    9 +
 .../hosts/carol/etc/swanctl/rsa/carolKey.pem       |   30 +
 .../hosts/carol/etc/swanctl/swanctl.conf           |   34 +
 .../rw-pubkey-keyid/hosts/dave/etc/strongswan.conf |   14 +
 .../hosts/dave/etc/swanctl/pubkey/davePub.pem      |    9 +
 .../hosts/dave/etc/swanctl/pubkey/moonPub.pem      |    9 +
 .../hosts/dave/etc/swanctl/swanctl.conf            |   26 +
 .../rw-pubkey-keyid/hosts/moon/etc/strongswan.conf |   14 +
 .../hosts/moon/etc/swanctl/pubkey/carolPub.pem     |    9 +
 .../hosts/moon/etc/swanctl/pubkey/davePub.pem      |    9 +
 .../hosts/moon/etc/swanctl/pubkey/moonPub.pem      |    9 +
 .../hosts/moon/etc/swanctl/swanctl.conf            |   20 +
 .../hosts/moon/etc/swanctl/swanctl_base.conf       |   16 +
 testing/tests/swanctl/rw-pubkey-keyid/posttest.dat |   11 +
 testing/tests/swanctl/rw-pubkey-keyid/pretest.dat  |   15 +
 testing/tests/swanctl/rw-pubkey-keyid/test.conf    |   25 +
 .../swanctl/shunt-policies-nat-rw/description.txt  |    7 +
 .../swanctl/shunt-policies-nat-rw/evaltest.dat     |   14 +
 .../hosts/alice/etc/strongswan.conf                |   11 +
 .../hosts/alice/etc/swanctl/swanctl.conf           |   40 +
 .../hosts/sun/etc/iptables.rules                   |   24 +
 .../hosts/sun/etc/strongswan.conf                  |   11 +
 .../hosts/sun/etc/swanctl/swanctl.conf             |   32 +
 .../hosts/venus/etc/strongswan.conf                |   11 +
 .../hosts/venus/etc/swanctl/swanctl.conf           |   40 +
 .../swanctl/shunt-policies-nat-rw/posttest.dat     |    5 +
 .../swanctl/shunt-policies-nat-rw/pretest.dat      |   11 +
 .../tests/swanctl/shunt-policies-nat-rw/test.conf  |   25 +
 testing/tests/swanctl/xauth-rsa/description.txt    |    9 +
 testing/tests/swanctl/xauth-rsa/evaltest.dat       |   12 +
 .../xauth-rsa/hosts/carol/etc/strongswan.conf      |   10 +
 .../xauth-rsa/hosts/carol/etc/swanctl/swanctl.conf |   38 +
 .../xauth-rsa/hosts/dave/etc/strongswan.conf       |   10 +
 .../xauth-rsa/hosts/dave/etc/swanctl/swanctl.conf  |   38 +
 .../xauth-rsa/hosts/moon/etc/strongswan.conf       |   10 +
 .../xauth-rsa/hosts/moon/etc/swanctl/swanctl.conf  |   40 +
 testing/tests/swanctl/xauth-rsa/posttest.dat       |    8 +
 testing/tests/swanctl/xauth-rsa/pretest.dat        |   11 +
 testing/tests/swanctl/xauth-rsa/test.conf          |   25 +
 testing/tests/tnc/tnccs-11-fhh/evaltest.dat        |   13 +-
 .../tnc/tnccs-11-fhh/hosts/carol/etc/init.d/charon |  158 +
 .../tnc/tnccs-11-fhh/hosts/carol/etc/ipsec.conf    |   23 -
 .../tnc/tnccs-11-fhh/hosts/carol/etc/ipsec.secrets |    3 -
 .../tnccs-11-fhh/hosts/carol/etc/strongswan.conf   |   18 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   35 +
 .../tnc/tnccs-11-fhh/hosts/dave/etc/init.d/charon  |  158 +
 .../tnc/tnccs-11-fhh/hosts/dave/etc/ipsec.conf     |   23 -
 .../tnc/tnccs-11-fhh/hosts/dave/etc/ipsec.secrets  |    3 -
 .../tnccs-11-fhh/hosts/dave/etc/strongswan.conf    |   18 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |   35 +
 .../tnc/tnccs-11-fhh/hosts/moon/etc/init.d/charon  |  158 +
 .../tnc/tnccs-11-fhh/hosts/moon/etc/ipsec.conf     |   34 -
 .../tnc/tnccs-11-fhh/hosts/moon/etc/ipsec.secrets  |    6 -
 .../tnccs-11-fhh/hosts/moon/etc/strongswan.conf    |   18 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   64 +
 testing/tests/tnc/tnccs-11-fhh/posttest.dat        |    6 +-
 testing/tests/tnc/tnccs-11-fhh/pretest.dat         |   14 +-
 testing/tests/tnc/tnccs-11-fhh/test.conf           |    4 +-
 .../tests/tnc/tnccs-11-radius-block/evaltest.dat   |    9 +-
 .../freeradius/sites-available/inner-tunnel-second |   13 +
 .../hosts/alice/etc/strongswan.conf                |   10 +-
 .../hosts/carol/etc/ipsec.conf                     |   23 -
 .../hosts/carol/etc/ipsec.secrets                  |    3 -
 .../hosts/carol/etc/strongswan.conf                |   15 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   35 +
 .../hosts/dave/etc/ipsec.conf                      |   23 -
 .../hosts/dave/etc/ipsec.secrets                   |    3 -
 .../hosts/dave/etc/strongswan.conf                 |   18 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |   35 +
 .../hosts/moon/etc/ipsec.conf                      |   23 -
 .../hosts/moon/etc/ipsec.secrets                   |    3 -
 .../hosts/moon/etc/strongswan.conf                 |   11 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   27 +
 .../tests/tnc/tnccs-11-radius-block/posttest.dat   |    7 +-
 .../tests/tnc/tnccs-11-radius-block/pretest.dat    |   18 +-
 testing/tests/tnc/tnccs-11-radius-block/test.conf  |    7 +-
 testing/tests/tnc/tnccs-11-radius-pts/evaltest.dat |   13 +-
 .../tnccs-11-radius-pts/hosts/carol/etc/ipsec.conf |   23 -
 .../hosts/carol/etc/ipsec.secrets                  |    3 -
 .../hosts/carol/etc/strongswan.conf                |   23 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   35 +
 .../tnccs-11-radius-pts/hosts/dave/etc/ipsec.conf  |   23 -
 .../hosts/dave/etc/ipsec.secrets                   |    3 -
 .../hosts/dave/etc/strongswan.conf                 |   27 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |   35 +
 .../tnccs-11-radius-pts/hosts/moon/etc/ipsec.conf  |   33 -
 .../hosts/moon/etc/ipsec.secrets                   |    3 -
 .../hosts/moon/etc/strongswan.conf                 |   10 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   53 +
 testing/tests/tnc/tnccs-11-radius-pts/posttest.dat |    6 +-
 testing/tests/tnc/tnccs-11-radius-pts/pretest.dat  |   16 +-
 testing/tests/tnc/tnccs-11-radius-pts/test.conf    |    4 +
 testing/tests/tnc/tnccs-11-radius/evaltest.dat     |   13 +-
 .../hosts/alice/etc/strongswan.conf                |    1 +
 .../tnc/tnccs-11-radius/hosts/carol/etc/ipsec.conf |   23 -
 .../tnccs-11-radius/hosts/carol/etc/ipsec.secrets  |    3 -
 .../hosts/carol/etc/strongswan.conf                |   15 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   35 +
 .../tnc/tnccs-11-radius/hosts/dave/etc/ipsec.conf  |   23 -
 .../tnccs-11-radius/hosts/dave/etc/ipsec.secrets   |    3 -
 .../tnccs-11-radius/hosts/dave/etc/strongswan.conf |   15 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |   35 +
 .../tnc/tnccs-11-radius/hosts/moon/etc/ipsec.conf  |   33 -
 .../tnccs-11-radius/hosts/moon/etc/ipsec.secrets   |    3 -
 .../tnccs-11-radius/hosts/moon/etc/strongswan.conf |   10 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   53 +
 testing/tests/tnc/tnccs-11-radius/posttest.dat     |    6 +-
 testing/tests/tnc/tnccs-11-radius/pretest.dat      |   14 +-
 testing/tests/tnc/tnccs-11-radius/test.conf        |    3 +
 .../hosts/alice/etc/strongswan.conf                |    1 +
 .../tnccs-11-supplicant/hosts/carol/etc/ipsec.conf |    1 -
 .../hosts/carol/etc/ipsec.secrets                  |    1 -
 .../hosts/carol/etc/strongswan.conf                |    1 +
 .../hosts/carol/etc/swanctl/swanctl.conf           |    1 +
 .../tnccs-11-supplicant/hosts/dave/etc/ipsec.conf  |    1 -
 .../hosts/dave/etc/ipsec.secrets                   |    1 -
 .../hosts/dave/etc/strongswan.conf                 |    1 +
 .../hosts/dave/etc/swanctl/swanctl.conf            |    1 +
 .../tnccs-11-supplicant/hosts/moon/etc/ipsec.conf  |   33 -
 .../hosts/moon/etc/ipsec.secrets                   |    3 -
 .../hosts/moon/etc/strongswan.conf                 |   13 -
 testing/tests/tnc/tnccs-11-supplicant/test.conf    |    7 +-
 testing/tests/tnc/tnccs-11/evaltest.dat            |   13 +-
 .../tests/tnc/tnccs-11/hosts/carol/etc/ipsec.conf  |   23 -
 .../tnc/tnccs-11/hosts/carol/etc/ipsec.secrets     |    3 -
 .../tnc/tnccs-11/hosts/carol/etc/strongswan.conf   |   19 +-
 .../tnccs-11/hosts/carol/etc/swanctl/swanctl.conf  |   35 +
 .../tests/tnc/tnccs-11/hosts/dave/etc/ipsec.conf   |   23 -
 .../tnc/tnccs-11/hosts/dave/etc/ipsec.secrets      |    3 -
 .../tnc/tnccs-11/hosts/dave/etc/strongswan.conf    |   19 +-
 .../tnccs-11/hosts/dave/etc/swanctl/swanctl.conf   |   35 +
 .../tests/tnc/tnccs-11/hosts/moon/etc/ipsec.conf   |   34 -
 .../tnc/tnccs-11/hosts/moon/etc/ipsec.secrets      |    6 -
 .../tnc/tnccs-11/hosts/moon/etc/strongswan.conf    |   19 +-
 .../tnccs-11/hosts/moon/etc/swanctl/swanctl.conf   |   64 +
 testing/tests/tnc/tnccs-11/posttest.dat            |    6 +-
 testing/tests/tnc/tnccs-11/pretest.dat             |   14 +-
 testing/tests/tnc/tnccs-11/test.conf               |    4 +
 testing/tests/tnc/tnccs-20-block/evaltest.dat      |    8 +-
 .../tnc/tnccs-20-block/hosts/carol/etc/ipsec.conf  |   23 -
 .../tnccs-20-block/hosts/carol/etc/ipsec.secrets   |    3 -
 .../tnccs-20-block/hosts/carol/etc/strongswan.conf |   19 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   34 +
 .../tnc/tnccs-20-block/hosts/dave/etc/ipsec.conf   |   23 -
 .../tnccs-20-block/hosts/dave/etc/ipsec.secrets    |    3 -
 .../tnccs-20-block/hosts/dave/etc/strongswan.conf  |   19 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |   34 +
 .../tnc/tnccs-20-block/hosts/moon/etc/ipsec.conf   |   24 -
 .../tnccs-20-block/hosts/moon/etc/ipsec.secrets    |    6 -
 .../tnccs-20-block/hosts/moon/etc/strongswan.conf  |   25 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   39 +
 testing/tests/tnc/tnccs-20-block/posttest.dat      |    7 +-
 testing/tests/tnc/tnccs-20-block/pretest.dat       |   15 +-
 testing/tests/tnc/tnccs-20-block/test.conf         |    3 +
 .../tests/tnc/tnccs-20-client-retry/evaltest.dat   |   14 +-
 .../hosts/carol/etc/ipsec.conf                     |   23 -
 .../hosts/carol/etc/ipsec.secrets                  |    3 -
 .../hosts/carol/etc/strongswan.conf                |   20 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   35 +
 .../hosts/dave/etc/ipsec.conf                      |   23 -
 .../hosts/dave/etc/ipsec.secrets                   |    3 -
 .../hosts/dave/etc/strongswan.conf                 |   19 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |   35 +
 .../hosts/moon/etc/ipsec.conf                      |   34 -
 .../hosts/moon/etc/ipsec.secrets                   |    6 -
 .../hosts/moon/etc/strongswan.conf                 |   19 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   64 +
 .../tests/tnc/tnccs-20-client-retry/posttest.dat   |    6 +-
 .../tests/tnc/tnccs-20-client-retry/pretest.dat    |   14 +-
 testing/tests/tnc/tnccs-20-client-retry/test.conf  |    3 +
 .../tnccs-20-fail-init/hosts/carol/etc/ipsec.conf  |   23 -
 .../hosts/carol/etc/ipsec.secrets                  |    3 -
 .../hosts/carol/etc/strongswan.conf                |   19 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   35 +
 .../tnccs-20-fail-init/hosts/dave/etc/ipsec.conf   |   23 -
 .../hosts/dave/etc/ipsec.secrets                   |    3 -
 .../hosts/dave/etc/strongswan.conf                 |   19 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |   35 +
 .../tnccs-20-fail-init/hosts/moon/etc/ipsec.conf   |   34 -
 .../hosts/moon/etc/ipsec.secrets                   |    6 -
 .../hosts/moon/etc/strongswan.conf                 |   19 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   64 +
 testing/tests/tnc/tnccs-20-fail-init/posttest.dat  |    6 +-
 testing/tests/tnc/tnccs-20-fail-init/pretest.dat   |   14 +-
 testing/tests/tnc/tnccs-20-fail-init/test.conf     |    3 +
 .../tnccs-20-fail-resp/hosts/carol/etc/ipsec.conf  |   23 -
 .../hosts/carol/etc/ipsec.secrets                  |    3 -
 .../hosts/carol/etc/strongswan.conf                |   20 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   35 +
 .../tnccs-20-fail-resp/hosts/moon/etc/ipsec.conf   |   34 -
 .../hosts/moon/etc/ipsec.secrets                   |    6 -
 .../hosts/moon/etc/strongswan.conf                 |   19 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   64 +
 testing/tests/tnc/tnccs-20-fail-resp/posttest.dat  |    4 +-
 testing/tests/tnc/tnccs-20-fail-resp/pretest.dat   |    8 +-
 testing/tests/tnc/tnccs-20-fail-resp/test.conf     |    3 +
 testing/tests/tnc/tnccs-20-fhh/evaltest.dat        |   17 +-
 .../tnc/tnccs-20-fhh/hosts/carol/etc/init.d/charon |  158 +
 .../tnc/tnccs-20-fhh/hosts/carol/etc/ipsec.conf    |   23 -
 .../tnc/tnccs-20-fhh/hosts/carol/etc/ipsec.secrets |    3 -
 .../tnccs-20-fhh/hosts/carol/etc/strongswan.conf   |   20 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   35 +
 .../tnc/tnccs-20-fhh/hosts/dave/etc/init.d/charon  |  158 +
 .../tnc/tnccs-20-fhh/hosts/dave/etc/ipsec.conf     |   23 -
 .../tnc/tnccs-20-fhh/hosts/dave/etc/ipsec.secrets  |    3 -
 .../tnccs-20-fhh/hosts/dave/etc/strongswan.conf    |   19 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |   35 +
 .../tnc/tnccs-20-fhh/hosts/moon/etc/init.d/charon  |  158 +
 .../tnc/tnccs-20-fhh/hosts/moon/etc/ipsec.conf     |   34 -
 .../tnc/tnccs-20-fhh/hosts/moon/etc/ipsec.secrets  |    6 -
 .../tnccs-20-fhh/hosts/moon/etc/strongswan.conf    |   15 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   64 +
 testing/tests/tnc/tnccs-20-fhh/posttest.dat        |    6 +-
 testing/tests/tnc/tnccs-20-fhh/pretest.dat         |   15 +-
 testing/tests/tnc/tnccs-20-fhh/test.conf           |    3 +
 testing/tests/tnc/tnccs-20-hcd-eap/evaltest.dat    |    1 -
 .../tnccs-20-hcd-eap/hosts/alice/etc/ipsec.conf    |    9 -
 .../tnccs-20-hcd-eap/hosts/alice/etc/ipsec.secrets |    3 -
 .../hosts/alice/etc/strongswan.conf                |   14 +-
 .../{ipsec.d/private => swanctl/rsa}/aaaKey.pem    |    0
 .../hosts/alice/etc/swanctl/swanctl.conf           |    0
 .../{ipsec.d/certs => swanctl/x509}/aaaCert.pem    |    0
 .../tnccs-20-hcd-eap/hosts/carol/etc/ipsec.conf    |   24 -
 .../hosts/carol/etc/strongswan.conf                |   19 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   27 +
 .../tnc/tnccs-20-hcd-eap/hosts/dave/etc/ipsec.conf |   24 -
 .../hosts/dave/etc/strongswan.conf                 |   19 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |   27 +
 .../tnc/tnccs-20-hcd-eap/hosts/moon/etc/ipsec.conf |   33 -
 .../tnccs-20-hcd-eap/hosts/moon/etc/ipsec.secrets  |    3 -
 .../hosts/moon/etc/strongswan.conf                 |    7 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   53 +
 testing/tests/tnc/tnccs-20-hcd-eap/posttest.dat    |   10 +-
 testing/tests/tnc/tnccs-20-hcd-eap/pretest.dat     |   14 +-
 testing/tests/tnc/tnccs-20-hcd-eap/test.conf       |    3 +
 .../tnc/tnccs-20-mutual-eap-fail/description.txt   |    5 +
 .../tnc/tnccs-20-mutual-eap-fail/evaltest.dat      |    7 +
 .../hosts/moon/etc/strongswan.conf                 |   45 +
 .../hosts/moon/etc/swanctl/swanctl.conf            |   28 +
 .../hosts/moon/etc/tnc_config                      |    4 +
 .../hosts/sun/etc/strongswan.conf                  |   47 +
 .../hosts/sun/etc/swanctl/swanctl.conf             |   28 +
 .../hosts/sun/etc/tnc_config                       |    4 +
 .../tnc/tnccs-20-mutual-eap-fail/posttest.dat      |    4 +
 .../tests/tnc/tnccs-20-mutual-eap-fail/pretest.dat |    6 +
 .../tests/tnc/tnccs-20-mutual-eap-fail/test.conf   |   25 +
 .../tests/tnc/tnccs-20-mutual-eap/description.txt  |    5 +-
 testing/tests/tnc/tnccs-20-mutual-eap/evaltest.dat |   12 +-
 .../tnccs-20-mutual-eap/hosts/moon/etc/ipsec.conf  |   23 -
 .../hosts/moon/etc/strongswan.conf                 |   23 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   28 +
 .../tnccs-20-mutual-eap/hosts/sun/etc/ipsec.conf   |   23 -
 .../hosts/sun/etc/strongswan.conf                  |   23 +-
 .../hosts/sun/etc/swanctl/swanctl.conf             |   28 +
 testing/tests/tnc/tnccs-20-mutual-eap/posttest.dat |    4 +-
 testing/tests/tnc/tnccs-20-mutual-eap/pretest.dat  |    8 +-
 testing/tests/tnc/tnccs-20-mutual-eap/test.conf    |    4 +
 .../hosts/moon/etc/ipsec.conf                      |    3 -
 .../hosts/moon/etc/pts/options                     |    6 +-
 .../hosts/moon/etc/strongswan.conf                 |    6 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |    1 +
 .../hosts/sun/etc/ipsec.conf                       |    9 -
 .../hosts/sun/etc/strongswan.conf                  |   19 +-
 .../hosts/sun/etc/swantcl/swanctl.conf             |    0
 .../tests/tnc/tnccs-20-mutual-pt-tls/posttest.dat  |    2 +-
 .../tests/tnc/tnccs-20-mutual-pt-tls/pretest.dat   |    4 +-
 testing/tests/tnc/tnccs-20-mutual-pt-tls/test.conf |    4 +
 testing/tests/tnc/tnccs-20-os-pts/evaltest.dat     |    8 +-
 .../tnc/tnccs-20-os-pts/hosts/carol/etc/ipsec.conf |   23 -
 .../tnccs-20-os-pts/hosts/carol/etc/ipsec.secrets  |    3 -
 .../hosts/carol/etc/strongswan.conf                |   21 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   35 +
 .../tnc/tnccs-20-os-pts/hosts/dave/etc/ipsec.conf  |   23 -
 .../tnccs-20-os-pts/hosts/dave/etc/ipsec.secrets   |    3 -
 .../tnccs-20-os-pts/hosts/dave/etc/strongswan.conf |   21 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |   35 +
 .../tnc/tnccs-20-os-pts/hosts/moon/etc/ipsec.conf  |   34 -
 .../tnccs-20-os-pts/hosts/moon/etc/ipsec.secrets   |    6 -
 .../tnccs-20-os-pts/hosts/moon/etc/strongswan.conf |   20 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   64 +
 testing/tests/tnc/tnccs-20-os-pts/posttest.dat     |    6 +-
 testing/tests/tnc/tnccs-20-os-pts/pretest.dat      |   16 +-
 testing/tests/tnc/tnccs-20-os-pts/test.conf        |    4 +
 testing/tests/tnc/tnccs-20-os/evaltest.dat         |    8 +-
 .../tnc/tnccs-20-os/hosts/carol/etc/ipsec.conf     |   23 -
 .../tnc/tnccs-20-os/hosts/carol/etc/ipsec.secrets  |    3 -
 .../tnccs-20-os/hosts/carol/etc/strongswan.conf    |   20 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   35 +
 .../tnc/tnccs-20-os/hosts/dave/etc/ipsec.conf      |   23 -
 .../tnc/tnccs-20-os/hosts/dave/etc/ipsec.secrets   |    3 -
 .../tnc/tnccs-20-os/hosts/dave/etc/strongswan.conf |   19 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |   35 +
 .../tnc/tnccs-20-os/hosts/moon/etc/ipsec.conf      |   34 -
 .../tnc/tnccs-20-os/hosts/moon/etc/ipsec.secrets   |    6 -
 .../tnc/tnccs-20-os/hosts/moon/etc/strongswan.conf |   19 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   64 +
 testing/tests/tnc/tnccs-20-os/posttest.dat         |    6 +-
 testing/tests/tnc/tnccs-20-os/pretest.dat          |   19 +-
 testing/tests/tnc/tnccs-20-os/test.conf            |    6 +-
 testing/tests/tnc/tnccs-20-pdp-eap/evaltest.dat    |    8 +-
 .../tnccs-20-pdp-eap/hosts/alice/etc/ipsec.conf    |    9 -
 .../tnccs-20-pdp-eap/hosts/alice/etc/ipsec.secrets |    6 -
 .../hosts/alice/etc/strongswan.conf                |   14 +-
 .../{ipsec.d/private => swanctl/rsa}/aaaKey.pem    |    0
 .../hosts/alice/etc/swanctl/swanctl.conf           |   11 +
 .../{ipsec.d/certs => swanctl/x509}/aaaCert.pem    |    0
 .../tnccs-20-pdp-eap/hosts/carol/etc/ipsec.conf    |   23 -
 .../tnccs-20-pdp-eap/hosts/carol/etc/ipsec.secrets |    3 -
 .../hosts/carol/etc/strongswan.conf                |   21 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   35 +
 .../tnc/tnccs-20-pdp-eap/hosts/dave/etc/ipsec.conf |   23 -
 .../tnccs-20-pdp-eap/hosts/dave/etc/ipsec.secrets  |    3 -
 .../hosts/dave/etc/strongswan.conf                 |   21 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |   35 +
 .../tnc/tnccs-20-pdp-eap/hosts/moon/etc/ipsec.conf |   33 -
 .../tnccs-20-pdp-eap/hosts/moon/etc/ipsec.secrets  |    3 -
 .../hosts/moon/etc/strongswan.conf                 |    8 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   53 +
 testing/tests/tnc/tnccs-20-pdp-eap/posttest.dat    |   10 +-
 testing/tests/tnc/tnccs-20-pdp-eap/pretest.dat     |   18 +-
 testing/tests/tnc/tnccs-20-pdp-eap/test.conf       |    3 +
 .../tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.conf |    9 -
 .../hosts/alice/etc/ipsec.secrets                  |    6 -
 .../hosts/alice/etc/strongswan.conf                |   15 +-
 .../{ipsec.d/private => swanctl/rsa}/aaaKey.pem    |    0
 .../hosts/alice/etc/swanctl/swanctl.conf           |    7 +
 .../{ipsec.d/certs => swanctl/x509}/aaaCert.pem    |    0
 .../tnccs-20-pdp-pt-tls/hosts/carol/etc/ipsec.conf |    3 -
 .../hosts/carol/etc/ipsec.secrets                  |    3 -
 .../hosts/carol/etc/pts/options                    |    2 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |    1 +
 .../tnccs-20-pdp-pt-tls/hosts/dave/etc/ipsec.conf  |    3 -
 .../hosts/dave/etc/ipsec.secrets                   |    3 -
 .../tnccs-20-pdp-pt-tls/hosts/dave/etc/pts/options |    6 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |    1 +
 .../tnccs-20-pdp-pt-tls/hosts/moon/etc/ipsec.conf  |    3 -
 .../hosts/moon/etc/ipsec.secrets                   |    3 -
 .../hosts/moon/etc/swanctl/swanctl.conf            |    1 +
 testing/tests/tnc/tnccs-20-pdp-pt-tls/posttest.dat |    4 +-
 testing/tests/tnc/tnccs-20-pdp-pt-tls/pretest.dat  |    4 +-
 testing/tests/tnc/tnccs-20-pdp-pt-tls/test.conf    |    4 +
 testing/tests/tnc/tnccs-20-pts-no-ecc/evaltest.dat |    8 +-
 .../tnccs-20-pts-no-ecc/hosts/carol/etc/ipsec.conf |   23 -
 .../hosts/carol/etc/ipsec.secrets                  |    3 -
 .../hosts/carol/etc/strongswan.conf                |   21 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   35 +
 .../tnccs-20-pts-no-ecc/hosts/dave/etc/ipsec.conf  |   23 -
 .../hosts/dave/etc/ipsec.secrets                   |    3 -
 .../hosts/dave/etc/strongswan.conf                 |   22 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |   35 +
 .../tnccs-20-pts-no-ecc/hosts/moon/etc/ipsec.conf  |   34 -
 .../hosts/moon/etc/ipsec.secrets                   |    6 -
 .../hosts/moon/etc/strongswan.conf                 |   20 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   64 +
 testing/tests/tnc/tnccs-20-pts-no-ecc/posttest.dat |    6 +-
 testing/tests/tnc/tnccs-20-pts-no-ecc/pretest.dat  |   14 +-
 testing/tests/tnc/tnccs-20-pts-no-ecc/test.conf    |    3 +
 testing/tests/tnc/tnccs-20-pts/evaltest.dat        |    8 +-
 .../hosts/carol/etc/.strongswan.conf.swp           |  Bin 0 -> 12288 bytes
 .../tnc/tnccs-20-pts/hosts/carol/etc/ipsec.conf    |   23 -
 .../tnc/tnccs-20-pts/hosts/carol/etc/ipsec.secrets |    3 -
 .../tnccs-20-pts/hosts/carol/etc/strongswan.conf   |   21 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   35 +
 .../tnc/tnccs-20-pts/hosts/dave/etc/ipsec.conf     |   23 -
 .../tnc/tnccs-20-pts/hosts/dave/etc/ipsec.secrets  |    3 -
 .../tnccs-20-pts/hosts/dave/etc/strongswan.conf    |   23 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |   35 +
 .../tnc/tnccs-20-pts/hosts/moon/etc/ipsec.conf     |   34 -
 .../tnc/tnccs-20-pts/hosts/moon/etc/ipsec.secrets  |    6 -
 .../tnccs-20-pts/hosts/moon/etc/strongswan.conf    |   22 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   64 +
 testing/tests/tnc/tnccs-20-pts/posttest.dat        |    6 +-
 testing/tests/tnc/tnccs-20-pts/pretest.dat         |   14 +-
 testing/tests/tnc/tnccs-20-pts/test.conf           |    3 +
 .../tests/tnc/tnccs-20-server-retry/evaltest.dat   |   13 +-
 .../hosts/carol/etc/ipsec.conf                     |   23 -
 .../hosts/carol/etc/ipsec.secrets                  |    3 -
 .../hosts/carol/etc/strongswan.conf                |   20 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   35 +
 .../hosts/dave/etc/ipsec.conf                      |   23 -
 .../hosts/dave/etc/ipsec.secrets                   |    3 -
 .../hosts/dave/etc/strongswan.conf                 |   19 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |   35 +
 .../hosts/moon/etc/ipsec.conf                      |   34 -
 .../hosts/moon/etc/ipsec.secrets                   |    6 -
 .../hosts/moon/etc/strongswan.conf                 |   19 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   64 +
 .../tests/tnc/tnccs-20-server-retry/posttest.dat   |    6 +-
 .../tests/tnc/tnccs-20-server-retry/pretest.dat    |   14 +-
 testing/tests/tnc/tnccs-20-server-retry/test.conf  |    3 +
 testing/tests/tnc/tnccs-20-tls/evaltest.dat        |   13 +-
 .../tnc/tnccs-20-tls/hosts/carol/etc/ipsec.conf    |   23 -
 .../tnccs-20-tls/hosts/carol/etc/strongswan.conf   |   20 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   27 +
 .../tnc/tnccs-20-tls/hosts/dave/etc/ipsec.conf     |   23 -
 .../tnccs-20-tls/hosts/dave/etc/strongswan.conf    |   20 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |   27 +
 .../tnc/tnccs-20-tls/hosts/moon/etc/ipsec.conf     |   34 -
 .../tnc/tnccs-20-tls/hosts/moon/etc/ipsec.secrets  |    6 -
 .../tnccs-20-tls/hosts/moon/etc/strongswan.conf    |   19 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   50 +
 testing/tests/tnc/tnccs-20-tls/posttest.dat        |    6 +-
 testing/tests/tnc/tnccs-20-tls/pretest.dat         |   10 +-
 testing/tests/tnc/tnccs-20-tls/test.conf           |    3 +
 testing/tests/tnc/tnccs-20/evaltest.dat            |   13 +-
 .../tests/tnc/tnccs-20/hosts/carol/etc/ipsec.conf  |   23 -
 .../tnc/tnccs-20/hosts/carol/etc/ipsec.secrets     |    3 -
 .../tnc/tnccs-20/hosts/carol/etc/strongswan.conf   |   20 +-
 .../tnccs-20/hosts/carol/etc/swanctl/swanctl.conf  |   35 +
 .../tests/tnc/tnccs-20/hosts/dave/etc/ipsec.conf   |   23 -
 .../tnc/tnccs-20/hosts/dave/etc/ipsec.secrets      |    3 -
 .../tnc/tnccs-20/hosts/dave/etc/strongswan.conf    |   19 +-
 .../tnccs-20/hosts/dave/etc/swanctl/swanctl.conf   |   35 +
 .../tests/tnc/tnccs-20/hosts/moon/etc/ipsec.conf   |   34 -
 .../tnc/tnccs-20/hosts/moon/etc/ipsec.secrets      |    6 -
 .../tnc/tnccs-20/hosts/moon/etc/strongswan.conf    |   19 +-
 .../tnccs-20/hosts/moon/etc/swanctl/swanctl.conf   |   64 +
 testing/tests/tnc/tnccs-20/posttest.dat            |    6 +-
 testing/tests/tnc/tnccs-20/pretest.dat             |   14 +-
 testing/tests/tnc/tnccs-20/test.conf               |    3 +
 testing/tests/tnc/tnccs-dynamic/evaltest.dat       |   13 +-
 .../tnc/tnccs-dynamic/hosts/carol/etc/ipsec.conf   |   23 -
 .../tnccs-dynamic/hosts/carol/etc/ipsec.secrets    |    3 -
 .../tnccs-dynamic/hosts/carol/etc/strongswan.conf  |   19 +-
 .../hosts/carol/etc/swanctl/swanctl.conf           |   35 +
 .../tnc/tnccs-dynamic/hosts/dave/etc/ipsec.conf    |   23 -
 .../tnc/tnccs-dynamic/hosts/dave/etc/ipsec.secrets |    3 -
 .../tnccs-dynamic/hosts/dave/etc/strongswan.conf   |   19 +-
 .../hosts/dave/etc/swanctl/swanctl.conf            |   35 +
 .../tnc/tnccs-dynamic/hosts/moon/etc/ipsec.conf    |   34 -
 .../tnc/tnccs-dynamic/hosts/moon/etc/ipsec.secrets |    6 -
 .../tnccs-dynamic/hosts/moon/etc/strongswan.conf   |   20 +-
 .../hosts/moon/etc/swanctl/swanctl.conf            |   64 +
 testing/tests/tnc/tnccs-dynamic/posttest.dat       |    6 +-
 testing/tests/tnc/tnccs-dynamic/pretest.dat        |   14 +-
 testing/tests/tnc/tnccs-dynamic/test.conf          |    3 +
 1547 files changed, 38974 insertions(+), 26297 deletions(-)

diff --git a/Android.common.mk b/Android.common.mk
index 41f508a..1aa5b53 100644
--- a/Android.common.mk
+++ b/Android.common.mk
@@ -26,5 +26,5 @@ add_plugin_subdirs = $(if $(call plugin_enabled,$(1)), \
               )
 
 # strongSwan version, replaced by top Makefile
-strongswan_VERSION := "5.3.5"
+strongswan_VERSION := "5.4.0"
 
diff --git a/Android.mk b/Android.mk
index 7b8bc8f..f17289e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -97,7 +97,6 @@ strongswan_CFLAGS += \
 strongswan_BUILD := \
 	charon \
 	libcharon \
-	libhydra \
 	libstrongswan \
 	libtncif \
 	libtnccs \
diff --git a/Makefile.in b/Makefile.in
index 22286fe..55ddc0e 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -444,6 +444,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/NEWS b/NEWS
index bda7068..8de6cac 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,43 @@
+strongswan-5.4.0
+----------------
+
+- Support for IKEv2 redirection (RFC 5685) has been added.  Plugins may
+  implement the redirect_provider_t interface to decide if and when to redirect
+  connecting clients.  It is also possible to redirect established IKE_SAs based
+  on different selectors via VICI/swanctl.  Unless disabled in strongswan.conf
+  the charon daemon will follow redirect requests received from servers.
+
+- The ike: prefix enables the explicit configuration of signature scheme
+  constraints against IKEv2 authentication in rightauth, which allows the use
+  of different signature schemes for trustchain verification and authentication.
+
+- The initiator of an IKEv2 make-before-break reauthentication now suspends
+  online certificate revocation checks (OCSP, CRLs) until the new IKE_SA and all
+  CHILD_SAs are established.  This is required if the checks are done over the
+  CHILD_SA established with the new IKE_SA.  This is not possible until the
+  initiator installs this SA and that only happens after the authentication is
+  completed successfully.  So we suspend the checks during the reauthentication
+  and do them afterwards, if they fail the IKE_SA is closed.  This change has no
+  effect on the behavior during the authentication of the initial IKE_SA.
+
+- For the vici plugin a Vici:Session Perl CPAN module has been added to allow
+  Perl applications to control and/or monitor the IKE daemon using the VICI
+  interface, similar to the existing Python egg or Ruby gem.
+
+- Traffic selectors with port ranges can now be configured in the Linux kernel:
+  e.g. remote_ts = 10.1.0.0/16[tcp/20-23] local_ts = dynamic[tcp/32768-65535].
+  The port range must map to a port mask, though since the kernel does not
+  support arbitrary ranges.
+
+- The vici plugin allows the configuration of IPv4 and IPv6 address ranges
+  in local and remote traffic selectors. Since both the Linux kernel and
+  iptables cannot handle arbitrary ranges, address ranges are mapped to the next
+  larger CIDR subnet by the kernel-netlink and updown plugins, respectively.
+
+- Implemented IKEv1 IPv4/IPv6 address subnet and range identities that can be
+  used as owners of shared secrets.
+
+
 strongswan-5.3.5
 ----------------
 
diff --git a/conf/Makefile.am b/conf/Makefile.am
index 72d9f25..b7edaa8 100644
--- a/conf/Makefile.am
+++ b/conf/Makefile.am
@@ -73,6 +73,7 @@ plugins = \
 	plugins/ntru.opt \
 	plugins/openssl.opt \
 	plugins/osx-attr.opt \
+	plugins/p-cscf.opt \
 	plugins/pkcs11.opt \
 	plugins/radattr.opt \
 	plugins/random.opt \
diff --git a/conf/Makefile.in b/conf/Makefile.in
index e6781b1..8bfc298 100644
--- a/conf/Makefile.in
+++ b/conf/Makefile.in
@@ -367,6 +367,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -455,6 +457,7 @@ plugins = \
 	plugins/ntru.opt \
 	plugins/openssl.opt \
 	plugins/osx-attr.opt \
+	plugins/p-cscf.opt \
 	plugins/pkcs11.opt \
 	plugins/radattr.opt \
 	plugins/random.opt \
diff --git a/conf/format-options.py b/conf/format-options.py
index d046e24..3073943 100755
--- a/conf/format-options.py
+++ b/conf/format-options.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #
-# Copyright (C) 2014 Tobias Brunner
+# Copyright (C) 2014-2015 Tobias Brunner
 # Hochschule fuer Technik Rapperswil
 #
 # This program is free software; you can redistribute it and/or modify it
@@ -48,6 +48,14 @@ full.section.name {[#]}
 
 If a # is added between the curly braces the section header will be commented
 out in the configuration file snippet, which is useful for example sections.
+
+Dots in section/option names may be escaped with a backslash.  For instance,
+with the following section description
+
+charon.filelog./var/log/daemon\.log {}
+	Section to define logging into /var/log/daemon.log
+
+/var/log/daemon.log will be the name of the last section.
 """
 
 import sys
@@ -58,9 +66,10 @@ from operator import attrgetter
 
 class ConfigOption:
 	"""Representing a configuration option or described section in strongswan.conf"""
-	def __init__(self, name, default = None, section = False, commented = False):
-		self.name = name.split('.')[-1]
-		self.fullname = name
+	def __init__(self, path, default = None, section = False, commented = False):
+		self.path = path
+		self.name = path[-1]
+		self.fullname = '.'.join(path)
 		self.default = default
 		self.section = section
 		self.commented = commented
@@ -68,7 +77,7 @@ class ConfigOption:
 		self.options = []
 
 	def __lt__(self, other):
-		return  self.name < other.name
+		return self.name < other.name
 
 	def add_paragraph(self):
 		"""Adds a new paragraph to the description"""
@@ -113,7 +122,8 @@ class Parser:
 		if m:
 			if self.__current:
 				self.__add_option(self.__current)
-			self.__current = ConfigOption(m.group('name'), m.group('default'),
+			path = self.__split_name(m.group('name'))
+			self.__current = ConfigOption(path, m.group('default'),
 										  commented = not m.group('assign'))
 			return
 		# section definition
@@ -121,7 +131,8 @@ class Parser:
 		if m:
 			if self.__current:
 				self.__add_option(self.__current)
-			self.__current = ConfigOption(m.group('name'), section = True,
+			path = self.__split_name(m.group('name'))
+			self.__current = ConfigOption(path, section = True,
 										  commented = m.group('comment'))
 			return
 		# paragraph separator
@@ -133,11 +144,14 @@ class Parser:
 		if m and self.__current:
 			self.__current.add(m.group('text'))
 
+	def __split_name(self, name):
+		"""Split the given full name in a list of section/option names"""
+		return [x.replace('\.', '.') for x in re.split(r'(?<!\\)\.', name)]
+
 	def __add_option(self, option):
 		"""Adds the given option to the abstract storage"""
 		option.desc = [desc for desc in option.desc if len(desc)]
-		parts = option.fullname.split('.')
-		parent = self.__get_option(parts[:-1], True)
+		parent = self.__get_option(option.path[:-1], True)
 		if not parent:
 			parent = self
 		found = next((x for x in parent.options if x.name == option.name
@@ -149,18 +163,16 @@ class Parser:
 			if self.sort:
 				parent.options.sort()
 
-	def __get_option(self, parts, create = False):
+	def __get_option(self, path, create = False):
 		"""Searches/Creates the option (section) based on a list of section names"""
 		option = None
 		options = self.options
-		fullname = ""
-		for name in parts:
-			fullname += '.' + name if len(fullname) else name
+		for i, name in enumerate(path, 1):
 			option = next((x for x in options if x.name == name and x.section), None)
 			if not option:
 				if not create:
 					break
-				option = ConfigOption(fullname, section = True)
+				option = ConfigOption(path[:i], section = True)
 				options.append(option)
 				if self.sort:
 					options.sort()
@@ -169,7 +181,7 @@ class Parser:
 
 	def get_option(self, name):
 		"""Retrieves the option with the given name"""
-		return self.__get_option(name.split('.'))
+		return self.__get_option(self.__split_name(name))
 
 class TagReplacer:
 	"""Replaces formatting tags in text"""
diff --git a/conf/options/charon.conf b/conf/options/charon.conf
index b55d429..5ca61a8 100644
--- a/conf/options/charon.conf
+++ b/conf/options/charon.conf
@@ -20,6 +20,9 @@ charon {
     # Number of half-open IKE_SAs that activate the cookie mechanism.
     # cookie_threshold = 10
 
+    # Delete CHILD_SAs right after they got successfully rekeyed (IKEv1 only).
+    # delete_rekeyed = no
+
     # Use ANSI X9.42 DH exponent size or optimum size matched to cryptographic
     # strength.
     # dh_exponent_ansi_x9_42 = yes
@@ -44,6 +47,9 @@ charon {
     # Free objects during authentication (might conflict with plugins).
     # flush_auth_cfg = no
 
+    # Whether to follow IKEv2 redirects (RFC 5685).
+    # follow_redirects = yes
+
     # Maximum size (complete IP datagram size in bytes) of a sent IKE fragment
     # when using proprietary IKEv1 or standardized IKEv2 fragmentation (0 for
     # address family specific        default values). If specified this limit is
@@ -188,7 +194,7 @@ charon {
     # DNS resolution failed), 0 to disable retries.
     # retry_initiate_interval = 0
 
-    # Initiate CHILD_SA within existing IKE_SAs.
+    # Initiate CHILD_SA within existing IKE_SAs (always enabled for IKEv1).
     # reuse_ikesa = yes
 
     # Numerical routing table to install routes to.
diff --git a/conf/options/charon.opt b/conf/options/charon.opt
index 816f325..86279ec 100644
--- a/conf/options/charon.opt
+++ b/conf/options/charon.opt
@@ -61,6 +61,14 @@ charon.crypto_test.required = no
 charon.crypto_test.rng_true = no
 	Whether to test RNG with TRUE quality; requires a lot of entropy.
 
+charon.delete_rekeyed = no
+	Delete CHILD_SAs right after they got successfully rekeyed (IKEv1 only).
+
+	Delete CHILD_SAs right after they got successfully rekeyed (IKEv1 only).
+	Reduces the number of stale CHILD_SAs in scenarios with a lot of rekeyings.
+	However, this might cause problems with implementations that continue to
+	use rekeyed SAs until they expire.
+
 charon.dh_exponent_ansi_x9_42 = yes
 	Use ANSI X9.42 DH exponent size or optimum size matched to cryptographic
 	strength.
@@ -89,6 +97,9 @@ charon.flush_auth_cfg = no
 	this might conflict with plugins that later need access to e.g. the used
 	certificates.
 
+charon.follow_redirects = yes
+	Whether to follow IKEv2 redirects (RFC 5685).
+
 charon.fragment_size = 0
 	Maximum size (complete IP datagram size in bytes) of a sent IKE fragment
 	when using proprietary IKEv1 or standardized IKEv2 fragmentation (0 for
@@ -283,7 +294,7 @@ charon.retry_initiate_interval = 0
 	resolution failed), 0 to disable retries.
 
 charon.reuse_ikesa = yes
-	Initiate CHILD_SA within existing IKE_SAs.
+	Initiate CHILD_SA within existing IKE_SAs (always enabled for IKEv1).
 
 charon.routing_table
 	Numerical routing table to install routes to.
diff --git a/conf/plugins/p-cscf.conf b/conf/plugins/p-cscf.conf
new file mode 100644
index 0000000..5225a7c
--- /dev/null
+++ b/conf/plugins/p-cscf.conf
@@ -0,0 +1,18 @@
+p-cscf {
+
+    # Whether to load the plugin. Can also be an integer to increase the
+    # priority of this plugin.
+    load = yes
+
+    # Section to enable requesting P-CSCF server addresses for individual
+    # connections.
+    enable {
+
+        # <conn> is the name of a connection with an ePDG from which to request
+        # P-CSCF server addresses.
+        # <conn> = no
+
+    }
+
+}
+
diff --git a/conf/plugins/p-cscf.opt b/conf/plugins/p-cscf.opt
new file mode 100644
index 0000000..ec7f815
--- /dev/null
+++ b/conf/plugins/p-cscf.opt
@@ -0,0 +1,11 @@
+charon.plugins.p-cscf.enable {}
+	Section to enable requesting P-CSCF server addresses for individual
+	connections.
+
+charon.plugins.p-cscf.enable.<conn> = no
+	<conn> is the name of a connection with an ePDG from which to request
+	P-CSCF server addresses.
+
+	<conn> is the name of a connection with an ePDG from which to request
+	P-CSCF server addresses.  Requests will be sent for addresses of the same
+	families for which internal IPs are requested.
diff --git a/conf/strongswan.conf.5.main b/conf/strongswan.conf.5.main
index 6335883..e6a5029 100644
--- a/conf/strongswan.conf.5.main
+++ b/conf/strongswan.conf.5.main
@@ -97,6 +97,13 @@ Strictly require at least one test vector to enable an algorithm.
 Whether to test RNG with TRUE quality; requires a lot of entropy.
 
 .TP
+.BR charon.delete_rekeyed " [no]"
+Delete CHILD_SAs right after they got successfully rekeyed (IKEv1 only). Reduces
+the number of stale CHILD_SAs in scenarios with a lot of rekeyings. However,
+this might cause problems with implementations that continue to use rekeyed SAs
+until they expire.
+
+.TP
 .BR charon.dh_exponent_ansi_x9_42 " [yes]"
 Use ANSI X9.42 DH exponent size or optimum size matched to cryptographic
 strength.
@@ -177,6 +184,10 @@ are released to free memory once an IKE_SA is established. Enabling this might
 conflict with plugins that later need access to e.g. the used certificates.
 
 .TP
+.BR charon.follow_redirects " [yes]"
+Whether to follow IKEv2 redirects (RFC 5685).
+
+.TP
 .BR charon.fragment_size " [0]"
 Maximum size (complete IP datagram size in bytes) of a sent IKE fragment when
 using proprietary IKEv1 or standardized IKEv2 fragmentation (0 for address
@@ -1191,6 +1202,17 @@ Set OpenSSL FIPS mode: disabled(0), enabled(1), Suite B enabled(2).
 Whether DNS servers are appended to existing entries, instead of replacing them.
 
 .TP
+.B charon.plugins.p-cscf.enable
+.br
+Section to enable requesting P\-CSCF server addresses for individual connections.
+
+.TP
+.BR charon.plugins.p-cscf.enable.<conn> " [no]"
+<conn> is the name of a connection with an ePDG from which to request P\-CSCF
+server addresses.  Requests will be sent for addresses of the same families for
+which internal IPs are requested.
+
+.TP
 .BR charon.plugins.pkcs11.load_certs " [yes]"
 Whether to load certificates from tokens.
 
@@ -1572,7 +1594,7 @@ resolution failed), 0 to disable retries.
 
 .TP
 .BR charon.reuse_ikesa " [yes]"
-Initiate CHILD_SA within existing IKE_SAs.
+Initiate CHILD_SA within existing IKE_SAs (always enabled for IKEv1).
 
 .TP
 .BR charon.routing_table " []"
diff --git a/config.h.in b/config.h.in
index b95e018..02528e7 100644
--- a/config.h.in
+++ b/config.h.in
@@ -329,6 +329,9 @@
 /* support for IKEv2 protocol */
 #undef USE_IKEV2
 
+/* use thread ID for thread identification, if available */
+#undef USE_THREAD_IDS
+
 /* use Vstr string library for printf hooks */
 #undef USE_VSTR
 
diff --git a/configure b/configure
index 3d0478c..dac40ea 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for strongSwan 5.3.5.
+# Generated by GNU Autoconf 2.69 for strongSwan 5.4.0.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -587,8 +587,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='strongSwan'
 PACKAGE_TARNAME='strongswan'
-PACKAGE_VERSION='5.3.5'
-PACKAGE_STRING='strongSwan 5.3.5'
+PACKAGE_VERSION='5.4.0'
+PACKAGE_STRING='strongSwan 5.4.0'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -635,6 +635,8 @@ LIBOBJS
 strongswan_options
 USE_PY_TEST_FALSE
 USE_PY_TEST_TRUE
+USE_PERL_CPAN_FALSE
+USE_PERL_CPAN_TRUE
 USE_PYTHON_EGGS_FALSE
 USE_PYTHON_EGGS_TRUE
 USE_RUBY_GEMS_FALSE
@@ -691,8 +693,6 @@ USE_LIBIPSEC_FALSE
 USE_LIBIPSEC_TRUE
 USE_LIBCHARON_FALSE
 USE_LIBCHARON_TRUE
-USE_LIBHYDRA_FALSE
-USE_LIBHYDRA_TRUE
 USE_LIBSTRONGSWAN_FALSE
 USE_LIBSTRONGSWAN_TRUE
 USE_CONFTEST_FALSE
@@ -731,12 +731,6 @@ USE_LOCK_PROFILER_FALSE
 USE_LOCK_PROFILER_TRUE
 USE_LEAK_DETECTIVE_FALSE
 USE_LEAK_DETECTIVE_TRUE
-USE_KERNEL_PFROUTE_FALSE
-USE_KERNEL_PFROUTE_TRUE
-USE_KERNEL_PFKEY_FALSE
-USE_KERNEL_PFKEY_TRUE
-USE_KERNEL_NETLINK_FALSE
-USE_KERNEL_NETLINK_TRUE
 USE_ATTR_SQL_FALSE
 USE_ATTR_SQL_TRUE
 USE_ATTR_FALSE
@@ -869,6 +863,12 @@ USE_KERNEL_WFP_FALSE
 USE_KERNEL_WFP_TRUE
 USE_KERNEL_LIBIPSEC_FALSE
 USE_KERNEL_LIBIPSEC_TRUE
+USE_KERNEL_PFROUTE_FALSE
+USE_KERNEL_PFROUTE_TRUE
+USE_KERNEL_PFKEY_FALSE
+USE_KERNEL_PFKEY_TRUE
+USE_KERNEL_NETLINK_FALSE
+USE_KERNEL_NETLINK_TRUE
 USE_HA_FALSE
 USE_HA_TRUE
 USE_LOAD_TESTER_FALSE
@@ -891,6 +891,8 @@ USE_ANDROID_LOG_FALSE
 USE_ANDROID_LOG_TRUE
 USE_ANDROID_DNS_FALSE
 USE_ANDROID_DNS_TRUE
+USE_P_CSCF_FALSE
+USE_P_CSCF_TRUE
 USE_OSX_ATTR_FALSE
 USE_OSX_ATTR_TRUE
 USE_UCI_FALSE
@@ -1025,6 +1027,8 @@ attest_plugins
 pool_plugins
 starter_plugins
 charon_plugins
+PERL_CPAN_INSTALL_FALSE
+PERL_CPAN_INSTALL_TRUE
 PYTHON_EGGS_INSTALL_FALSE
 PYTHON_EGGS_INSTALL_TRUE
 PY_TEST
@@ -1068,6 +1072,8 @@ systemd_journal_LIBS
 systemd_journal_CFLAGS
 systemd_daemon_LIBS
 systemd_daemon_CFLAGS
+systemd_LIBS
+systemd_CFLAGS
 xml_LIBS
 xml_CFLAGS
 soup_LIBS
@@ -1374,6 +1380,7 @@ enable_attr
 enable_attr_sql
 enable_dhcp
 enable_osx_attr
+enable_p_cscf
 enable_resolve
 enable_unity
 enable_imc_test
@@ -1441,9 +1448,12 @@ enable_ruby_gems
 enable_ruby_gems_install
 enable_python_eggs
 enable_python_eggs_install
+enable_perl_cpan
+enable_perl_cpan_install
 enable_coverage
 enable_leak_detective
 enable_lock_profiler
+enable_log_thread_ids
 enable_monolithic
 enable_defaults
 enable_all
@@ -1476,6 +1486,8 @@ soup_CFLAGS
 soup_LIBS
 xml_CFLAGS
 xml_LIBS
+systemd_CFLAGS
+systemd_LIBS
 systemd_daemon_CFLAGS
 systemd_daemon_LIBS
 systemd_journal_CFLAGS
@@ -2032,7 +2044,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures strongSwan 5.3.5 to adapt to many kinds of systems.
+\`configure' configures strongSwan 5.4.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -2102,7 +2114,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of strongSwan 5.3.5:";;
+     short | recursive ) echo "Configuration of strongSwan 5.4.0:";;
    esac
   cat <<\_ACEOF
 
@@ -2230,13 +2242,15 @@ Optional Features:
                           Requires libxml.
   --enable-sql            enable SQL database configuration backend.
   --enable-uci            enable OpenWRT UCI configuration plugin.
-  --enable-vici           enable strongSwan IKE generic IPC interface plugin.
+  --disable-vici          disable strongSwan IKE generic IPC interface plugin.
   --enable-android-dns    enable Android specific DNS handler.
   --disable-attr          disable strongswan.conf based configuration
                           attribute plugin.
   --enable-attr-sql       enable SQL based configuration attribute plugin.
   --enable-dhcp           enable DHCP based attribute provider plugin.
   --enable-osx-attr       enable OS X SystemConfiguration attribute handler.
+  --enable-p-cscf         enable plugin to request P-CSCF server addresses
+                          from an ePDG.
   --disable-resolve       disable resolve DNS handler plugin.
   --enable-unity          enables Cisco Unity extension plugin.
   --enable-imc-test       enable IMC test module.
@@ -2305,7 +2319,7 @@ Optional Features:
                           scripts).
   --enable-svc            enable charon Windows service.
   --enable-systemd        enable systemd specific IKE daemon charon-systemd.
-  --enable-swanctl        enable swanctl configuration and control tool.
+  --disable-swanctl       disable swanctl configuration and control tool.
   --enable-tkm            enable Trusted Key Manager support.
   --enable-bfd-backtraces use binutils libbfd to resolve backtraces for memory
                           leaks and segfaults.
@@ -2328,9 +2342,15 @@ Optional Features:
   --enable-python-eggs    enable build of provided python eggs.
   --enable-python-eggs-install
                           enable installation of provided python eggs.
+  --enable-perl-cpan      enable build of provided perl CPAN module.
+  --enable-perl-cpan-install
+                          enable installation of provided CPAN module.
   --enable-coverage       enable lcov coverage report generation.
   --enable-leak-detective enable malloc hooks to find memory leaks.
   --enable-lock-profiler  enable lock/mutex profiling code.
+  --enable-log-thread-ids use thread ID, if available, instead of an
+                          incremented value starting from 1, to identify
+                          threads.
   --enable-monolithic     build monolithic version of libstrongswan that
                           includes all enabled plugins. Similarly, the plugins
                           of charon are assembled in libcharon.
@@ -2453,6 +2473,10 @@ Some influential environment variables:
   soup_LIBS   linker flags for soup, overriding pkg-config
   xml_CFLAGS  C compiler flags for xml, overriding pkg-config
   xml_LIBS    linker flags for xml, overriding pkg-config
+  systemd_CFLAGS
+              C compiler flags for systemd, overriding pkg-config
+  systemd_LIBS
+              linker flags for systemd, overriding pkg-config
   systemd_daemon_CFLAGS
               C compiler flags for systemd_daemon, overriding pkg-config
   systemd_daemon_LIBS
@@ -2545,7 +2569,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-strongSwan configure 5.3.5
+strongSwan configure 5.4.0
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -3067,7 +3091,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by strongSwan $as_me 5.3.5, which was
+It was created by strongSwan $as_me 5.4.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3930,7 +3954,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='strongswan'
- VERSION='5.3.5'
+ VERSION='5.4.0'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -6286,12 +6310,12 @@ if test "${enable_vici+set}" = set; then :
 			vici=false
 		fi
 else
-  vici=false
+  vici=true
 		vici_given=false
 
 fi
 
-	disabled_by_default=${disabled_by_default}" vici"
+	enabled_by_default=${enabled_by_default}" vici"
 
 # attribute provider/consumer plugins
 # Check whether --enable-android-dns was given.
@@ -6374,6 +6398,22 @@ fi
 
 	disabled_by_default=${disabled_by_default}" osx_attr"
 
+# Check whether --enable-p-cscf was given.
+if test "${enable_p_cscf+set}" = set; then :
+  enableval=$enable_p_cscf; p_cscf_given=true
+		if test x$enableval = xyes; then
+			p_cscf=true
+		 else
+			p_cscf=false
+		fi
+else
+  p_cscf=false
+		p_cscf_given=false
+
+fi
+
+	disabled_by_default=${disabled_by_default}" p_cscf"
+
 # Check whether --enable-resolve was given.
 if test "${enable_resolve+set}" = set; then :
   enableval=$enable_resolve; resolve_given=true
@@ -7234,12 +7274,12 @@ if test "${enable_swanctl+set}" = set; then :
 			swanctl=false
 		fi
 else
-  swanctl=false
+  swanctl=true
 		swanctl_given=false
 
 fi
 
-	disabled_by_default=${disabled_by_default}" swanctl"
+	enabled_by_default=${enabled_by_default}" swanctl"
 
 # Check whether --enable-tkm was given.
 if test "${enable_tkm+set}" = set; then :
@@ -7450,6 +7490,38 @@ fi
 
 	disabled_by_default=${disabled_by_default}" python_eggs_install"
 
+# Check whether --enable-perl-cpan was given.
+if test "${enable_perl_cpan+set}" = set; then :
+  enableval=$enable_perl_cpan; perl_cpan_given=true
+		if test x$enableval = xyes; then
+			perl_cpan=true
+		 else
+			perl_cpan=false
+		fi
+else
+  perl_cpan=false
+		perl_cpan_given=false
+
+fi
+
+	disabled_by_default=${disabled_by_default}" perl_cpan"
+
+# Check whether --enable-perl-cpan-install was given.
+if test "${enable_perl_cpan_install+set}" = set; then :
+  enableval=$enable_perl_cpan_install; perl_cpan_install_given=true
+		if test x$enableval = xyes; then
+			perl_cpan_install=true
+		 else
+			perl_cpan_install=false
+		fi
+else
+  perl_cpan_install=false
+		perl_cpan_install_given=false
+
+fi
+
+	disabled_by_default=${disabled_by_default}" perl_cpan_install"
+
 # compile options
 # Check whether --enable-coverage was given.
 if test "${enable_coverage+set}" = set; then :
@@ -7499,6 +7571,22 @@ fi
 
 	disabled_by_default=${disabled_by_default}" lock_profiler"
 
+# Check whether --enable-log-thread-ids was given.
+if test "${enable_log_thread_ids+set}" = set; then :
+  enableval=$enable_log_thread_ids; log_thread_ids_given=true
+		if test x$enableval = xyes; then
+			log_thread_ids=true
+		 else
+			log_thread_ids=false
+		fi
+else
+  log_thread_ids=false
+		log_thread_ids_given=false
+
+fi
+
+	disabled_by_default=${disabled_by_default}" log_thread_ids"
+
 # Check whether --enable-monolithic was given.
 if test "${enable_monolithic+set}" = set; then :
   enableval=$enable_monolithic; monolithic_given=true
@@ -17328,6 +17416,10 @@ if test x$python_eggs_install = xtrue; then
 	python_eggs=true
 fi
 
+if test x$perl_cpan_install = xtrue; then
+	perl_cpan=true
+fi
+
 # ===========================================
 #  check required libraries and header files
 # ===========================================
@@ -19498,6 +19590,65 @@ $as_echo "$systemdsystemunitdir" >&6; }
 
 
 pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for systemd" >&5
+$as_echo_n "checking for systemd... " >&6; }
+
+if test -n "$systemd_CFLAGS"; then
+    pkg_cv_systemd_CFLAGS="$systemd_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd >= 209\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libsystemd >= 209") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_systemd_CFLAGS=`$PKG_CONFIG --cflags "libsystemd >= 209" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$systemd_LIBS"; then
+    pkg_cv_systemd_LIBS="$systemd_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd >= 209\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libsystemd >= 209") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_systemd_LIBS=`$PKG_CONFIG --libs "libsystemd >= 209" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        systemd_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd >= 209" 2>&1`
+        else
+	        systemd_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd >= 209" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$systemd_PKG_ERRORS" >&5
+
+
+pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for systemd_daemon" >&5
 $as_echo_n "checking for systemd_daemon... " >&6; }
 
@@ -19590,6 +19741,195 @@ fi
 
 
 
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for systemd_journal" >&5
+$as_echo_n "checking for systemd_journal... " >&6; }
+
+if test -n "$systemd_journal_CFLAGS"; then
+    pkg_cv_systemd_journal_CFLAGS="$systemd_journal_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-journal\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libsystemd-journal") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_systemd_journal_CFLAGS=`$PKG_CONFIG --cflags "libsystemd-journal" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$systemd_journal_LIBS"; then
+    pkg_cv_systemd_journal_LIBS="$systemd_journal_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-journal\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libsystemd-journal") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_systemd_journal_LIBS=`$PKG_CONFIG --libs "libsystemd-journal" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        systemd_journal_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd-journal" 2>&1`
+        else
+	        systemd_journal_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd-journal" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$systemd_journal_PKG_ERRORS" >&5
+
+	as_fn_error $? "Package requirements (libsystemd-journal) were not met:
+
+$systemd_journal_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables systemd_journal_CFLAGS
+and systemd_journal_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables systemd_journal_CFLAGS
+and systemd_journal_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+	systemd_journal_CFLAGS=$pkg_cv_systemd_journal_CFLAGS
+	systemd_journal_LIBS=$pkg_cv_systemd_journal_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+
+
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for systemd_daemon" >&5
+$as_echo_n "checking for systemd_daemon... " >&6; }
+
+if test -n "$systemd_daemon_CFLAGS"; then
+    pkg_cv_systemd_daemon_CFLAGS="$systemd_daemon_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-daemon\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libsystemd-daemon") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_systemd_daemon_CFLAGS=`$PKG_CONFIG --cflags "libsystemd-daemon" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$systemd_daemon_LIBS"; then
+    pkg_cv_systemd_daemon_LIBS="$systemd_daemon_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-daemon\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libsystemd-daemon") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_systemd_daemon_LIBS=`$PKG_CONFIG --libs "libsystemd-daemon" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        systemd_daemon_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd-daemon" 2>&1`
+        else
+	        systemd_daemon_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd-daemon" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$systemd_daemon_PKG_ERRORS" >&5
+
+	as_fn_error $? "Package requirements (libsystemd-daemon) were not met:
+
+$systemd_daemon_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables systemd_daemon_CFLAGS
+and systemd_daemon_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables systemd_daemon_CFLAGS
+and systemd_daemon_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+	systemd_daemon_CFLAGS=$pkg_cv_systemd_daemon_CFLAGS
+	systemd_daemon_LIBS=$pkg_cv_systemd_daemon_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+
 
 pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for systemd_journal" >&5
@@ -19683,6 +20023,15 @@ $as_echo "yes" >&6; }
 fi
 
 
+
+else
+	systemd_CFLAGS=$pkg_cv_systemd_CFLAGS
+	systemd_LIBS=$pkg_cv_systemd_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+
+fi
 fi
 
 if test x$tss = xtrousers; then
@@ -20556,7 +20905,7 @@ if eval \${$as_ac_Lib+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-l$openssl_lib  $LIBS"
+LIBS="-l$openssl_lib $DLLIB $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -21861,6 +22210,15 @@ else
 fi
 
 
+ if test "x$perl_cpan_install" = xtrue; then
+  PERL_CPAN_INSTALL_TRUE=
+  PERL_CPAN_INSTALL_FALSE='#'
+else
+  PERL_CPAN_INSTALL_TRUE='#'
+  PERL_CPAN_INSTALL_FALSE=
+fi
+
+
 # ===============================================
 #  collect plugin list for strongSwan components
 # ===============================================
@@ -21886,9 +22244,8 @@ cmd_plugins=
 aikgen_plugins=
 
 # location specific lists for checksumming,
-# for src/libcharon, src/libhydra, src/libstrongswan and src/libtnccs
+# for src/libcharon, src/libstrongswan and src/libtnccs
 c_plugins=
-h_plugins=
 s_plugins=
 t_plugins=
 
@@ -21984,21 +22341,6 @@ if test x$rc2 = xtrue; then
 
 	fi
 
-if test x$sha1 = xtrue; then
-		s_plugins=${s_plugins}" sha1"
-		charon_plugins=${charon_plugins}" sha1"
-		scepclient_plugins=${scepclient_plugins}" sha1"
-		pki_plugins=${pki_plugins}" sha1"
-		scripts_plugins=${scripts_plugins}" sha1"
-		manager_plugins=${manager_plugins}" sha1"
-		medsrv_plugins=${medsrv_plugins}" sha1"
-		attest_plugins=${attest_plugins}" sha1"
-		nm_plugins=${nm_plugins}" sha1"
-		cmd_plugins=${cmd_plugins}" sha1"
-		aikgen_plugins=${aikgen_plugins}" sha1"
-
-	fi
-
 if test x$sha2 = xtrue; then
 		s_plugins=${s_plugins}" sha2"
 		charon_plugins=${charon_plugins}" sha2"
@@ -22027,6 +22369,21 @@ if test x$sha3 = xtrue; then
 
 	fi
 
+if test x$sha1 = xtrue; then
+		s_plugins=${s_plugins}" sha1"
+		charon_plugins=${charon_plugins}" sha1"
+		scepclient_plugins=${scepclient_plugins}" sha1"
+		pki_plugins=${pki_plugins}" sha1"
+		scripts_plugins=${scripts_plugins}" sha1"
+		manager_plugins=${manager_plugins}" sha1"
+		medsrv_plugins=${medsrv_plugins}" sha1"
+		attest_plugins=${attest_plugins}" sha1"
+		nm_plugins=${nm_plugins}" sha1"
+		cmd_plugins=${cmd_plugins}" sha1"
+		aikgen_plugins=${aikgen_plugins}" sha1"
+
+	fi
+
 if test x$md4 = xtrue; then
 		s_plugins=${s_plugins}" md4"
 		charon_plugins=${charon_plugins}" md4"
@@ -22498,7 +22855,7 @@ if test x$kernel_iph = xtrue; then
 	fi
 
 if test x$kernel_pfkey = xtrue; then
-		h_plugins=${h_plugins}" kernel-pfkey"
+		c_plugins=${c_plugins}" kernel-pfkey"
 		charon_plugins=${charon_plugins}" kernel-pfkey"
 		starter_plugins=${starter_plugins}" kernel-pfkey"
 		nm_plugins=${nm_plugins}" kernel-pfkey"
@@ -22507,7 +22864,7 @@ if test x$kernel_pfkey = xtrue; then
 	fi
 
 if test x$kernel_pfroute = xtrue; then
-		h_plugins=${h_plugins}" kernel-pfroute"
+		c_plugins=${c_plugins}" kernel-pfroute"
 		charon_plugins=${charon_plugins}" kernel-pfroute"
 		starter_plugins=${starter_plugins}" kernel-pfroute"
 		nm_plugins=${nm_plugins}" kernel-pfroute"
@@ -22516,7 +22873,7 @@ if test x$kernel_pfroute = xtrue; then
 	fi
 
 if test x$kernel_netlink = xtrue; then
-		h_plugins=${h_plugins}" kernel-netlink"
+		c_plugins=${c_plugins}" kernel-netlink"
 		charon_plugins=${charon_plugins}" kernel-netlink"
 		starter_plugins=${starter_plugins}" kernel-netlink"
 		nm_plugins=${nm_plugins}" kernel-netlink"
@@ -22820,6 +23177,13 @@ if test x$osx_attr = xtrue; then
 
 	fi
 
+if test x$p_cscf = xtrue; then
+		c_plugins=${c_plugins}" p-cscf"
+		charon_plugins=${charon_plugins}" p-cscf"
+		cmd_plugins=${cmd_plugins}" p-cscf"
+
+	fi
+
 if test x$android_dns = xtrue; then
 		c_plugins=${c_plugins}" android-dns"
 		charon_plugins=${charon_plugins}" android-dns"
@@ -23422,6 +23786,14 @@ else
   USE_OSX_ATTR_FALSE=
 fi
 
+ if test x$p_cscf = xtrue; then
+  USE_P_CSCF_TRUE=
+  USE_P_CSCF_FALSE='#'
+else
+  USE_P_CSCF_TRUE='#'
+  USE_P_CSCF_FALSE=
+fi
+
  if test x$android_dns = xtrue; then
   USE_ANDROID_DNS_TRUE=
   USE_ANDROID_DNS_FALSE='#'
@@ -23510,6 +23882,30 @@ else
   USE_HA_FALSE=
 fi
 
+ if test x$kernel_netlink = xtrue; then
+  USE_KERNEL_NETLINK_TRUE=
+  USE_KERNEL_NETLINK_FALSE='#'
+else
+  USE_KERNEL_NETLINK_TRUE='#'
+  USE_KERNEL_NETLINK_FALSE=
+fi
+
+ if test x$kernel_pfkey = xtrue; then
+  USE_KERNEL_PFKEY_TRUE=
+  USE_KERNEL_PFKEY_FALSE='#'
+else
+  USE_KERNEL_PFKEY_TRUE='#'
+  USE_KERNEL_PFKEY_FALSE=
+fi
+
+ if test x$kernel_pfroute = xtrue; then
+  USE_KERNEL_PFROUTE_TRUE=
+  USE_KERNEL_PFROUTE_FALSE='#'
+else
+  USE_KERNEL_PFROUTE_TRUE='#'
+  USE_KERNEL_PFROUTE_FALSE=
+fi
+
  if test x$kernel_libipsec = xtrue; then
   USE_KERNEL_LIBIPSEC_TRUE=
   USE_KERNEL_LIBIPSEC_FALSE='#'
@@ -24039,33 +24435,6 @@ else
 fi
 
 
-#  hydra plugins
-# ---------------
- if test x$kernel_netlink = xtrue; then
-  USE_KERNEL_NETLINK_TRUE=
-  USE_KERNEL_NETLINK_FALSE='#'
-else
-  USE_KERNEL_NETLINK_TRUE='#'
-  USE_KERNEL_NETLINK_FALSE=
-fi
-
- if test x$kernel_pfkey = xtrue; then
-  USE_KERNEL_PFKEY_TRUE=
-  USE_KERNEL_PFKEY_FALSE='#'
-else
-  USE_KERNEL_PFKEY_TRUE='#'
-  USE_KERNEL_PFKEY_FALSE=
-fi
-
- if test x$kernel_pfroute = xtrue; then
-  USE_KERNEL_PFROUTE_TRUE=
-  USE_KERNEL_PFROUTE_FALSE='#'
-else
-  USE_KERNEL_PFROUTE_TRUE='#'
-  USE_KERNEL_PFROUTE_FALSE=
-fi
-
-
 #  other options
 # ---------------
  if test x$leak_detective = xtrue; then
@@ -24220,14 +24589,6 @@ else
   USE_LIBSTRONGSWAN_FALSE=
 fi
 
- if test x$charon = xtrue -o x$nm = xtrue -o x$tkm = xtrue -o x$cmd = xtrue -o x$svc = xtrue -o x$systemd = xtrue; then
-  USE_LIBHYDRA_TRUE=
-  USE_LIBHYDRA_FALSE='#'
-else
-  USE_LIBHYDRA_TRUE='#'
-  USE_LIBHYDRA_FALSE=
-fi
-
  if test x$charon = xtrue -o x$conftest = xtrue -o x$nm = xtrue -o x$tkm = xtrue -o x$cmd = xtrue -o x$svc = xtrue -o x$systemd = xtrue; then
   USE_LIBCHARON_TRUE=
   USE_LIBCHARON_FALSE='#'
@@ -24452,6 +24813,14 @@ else
   USE_PYTHON_EGGS_FALSE=
 fi
 
+ if test x$perl_cpan = xtrue; then
+  USE_PERL_CPAN_TRUE=
+  USE_PERL_CPAN_FALSE='#'
+else
+  USE_PERL_CPAN_TRUE='#'
+  USE_PERL_CPAN_FALSE=
+fi
+
  if test "x$PY_TEST" != x; then
   USE_PY_TEST_TRUE=
   USE_PY_TEST_FALSE='#'
@@ -24475,6 +24844,11 @@ if test x$capabilities = xlibcap -o x$capabilities = xnative; then
 $as_echo "#define CAPABILITIES /**/" >>confdefs.h
 
 fi
+if test x$log_thread_ids = xtrue; then
+
+$as_echo "#define USE_THREAD_IDS /**/" >>confdefs.h
+
+fi
 if test x$monolithic = xtrue; then
 
 $as_echo "#define MONOLITHIC /**/" >>confdefs.h
@@ -24543,7 +24917,7 @@ fi
 #  build Makefiles
 # =================
 
-ac_config_files="$ac_config_files Makefile conf/Makefile man/Makefile init/Makefile init/systemd/Makefile init/systemd-swanctl/Makefile src/Makefile src/include/Makefile src/libstrongswan/Makefile src/libstrongswan/plugins/aes/Makefile src/libstrongswan/plugins/cmac/Makefile src/libstrongswan/plugins/des/Makefile src/libstrongswan/plugins/blowfish/Makefile src/libstrongswan/plugins/rc2/Makefile src/libstrongswan/plugins/md4/Makefile src/libstrongswan/plugins/md5/Makefile src/libstrongswa [...]
+ac_config_files="$ac_config_files Makefile conf/Makefile man/Makefile init/Makefile init/systemd/Makefile init/systemd-swanctl/Makefile src/Makefile src/include/Makefile src/libstrongswan/Makefile src/libstrongswan/plugins/aes/Makefile src/libstrongswan/plugins/cmac/Makefile src/libstrongswan/plugins/des/Makefile src/libstrongswan/plugins/blowfish/Makefile src/libstrongswan/plugins/rc2/Makefile src/libstrongswan/plugins/md4/Makefile src/libstrongswan/plugins/md5/Makefile src/libstrongswa [...]
 
 
 # =================
@@ -24711,6 +25085,10 @@ if test -z "${PYTHON_EGGS_INSTALL_TRUE}" && test -z "${PYTHON_EGGS_INSTALL_FALSE
   as_fn_error $? "conditional \"PYTHON_EGGS_INSTALL\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${PERL_CPAN_INSTALL_TRUE}" && test -z "${PERL_CPAN_INSTALL_FALSE}"; then
+  as_fn_error $? "conditional \"PERL_CPAN_INSTALL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${USE_TEST_VECTORS_TRUE}" && test -z "${USE_TEST_VECTORS_FALSE}"; then
   as_fn_error $? "conditional \"USE_TEST_VECTORS\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -24947,6 +25325,10 @@ if test -z "${USE_OSX_ATTR_TRUE}" && test -z "${USE_OSX_ATTR_FALSE}"; then
   as_fn_error $? "conditional \"USE_OSX_ATTR\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${USE_P_CSCF_TRUE}" && test -z "${USE_P_CSCF_FALSE}"; then
+  as_fn_error $? "conditional \"USE_P_CSCF\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${USE_ANDROID_DNS_TRUE}" && test -z "${USE_ANDROID_DNS_FALSE}"; then
   as_fn_error $? "conditional \"USE_ANDROID_DNS\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -24991,6 +25373,18 @@ if test -z "${USE_HA_TRUE}" && test -z "${USE_HA_FALSE}"; then
   as_fn_error $? "conditional \"USE_HA\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${USE_KERNEL_NETLINK_TRUE}" && test -z "${USE_KERNEL_NETLINK_FALSE}"; then
+  as_fn_error $? "conditional \"USE_KERNEL_NETLINK\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${USE_KERNEL_PFKEY_TRUE}" && test -z "${USE_KERNEL_PFKEY_FALSE}"; then
+  as_fn_error $? "conditional \"USE_KERNEL_PFKEY\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${USE_KERNEL_PFROUTE_TRUE}" && test -z "${USE_KERNEL_PFROUTE_FALSE}"; then
+  as_fn_error $? "conditional \"USE_KERNEL_PFROUTE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${USE_KERNEL_LIBIPSEC_TRUE}" && test -z "${USE_KERNEL_LIBIPSEC_FALSE}"; then
   as_fn_error $? "conditional \"USE_KERNEL_LIBIPSEC\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -25255,18 +25649,6 @@ if test -z "${USE_ATTR_SQL_TRUE}" && test -z "${USE_ATTR_SQL_FALSE}"; then
   as_fn_error $? "conditional \"USE_ATTR_SQL\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${USE_KERNEL_NETLINK_TRUE}" && test -z "${USE_KERNEL_NETLINK_FALSE}"; then
-  as_fn_error $? "conditional \"USE_KERNEL_NETLINK\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${USE_KERNEL_PFKEY_TRUE}" && test -z "${USE_KERNEL_PFKEY_FALSE}"; then
-  as_fn_error $? "conditional \"USE_KERNEL_PFKEY\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${USE_KERNEL_PFROUTE_TRUE}" && test -z "${USE_KERNEL_PFROUTE_FALSE}"; then
-  as_fn_error $? "conditional \"USE_KERNEL_PFROUTE\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
 if test -z "${USE_LEAK_DETECTIVE_TRUE}" && test -z "${USE_LEAK_DETECTIVE_FALSE}"; then
   as_fn_error $? "conditional \"USE_LEAK_DETECTIVE\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -25343,10 +25725,6 @@ if test -z "${USE_LIBSTRONGSWAN_TRUE}" && test -z "${USE_LIBSTRONGSWAN_FALSE}";
   as_fn_error $? "conditional \"USE_LIBSTRONGSWAN\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${USE_LIBHYDRA_TRUE}" && test -z "${USE_LIBHYDRA_FALSE}"; then
-  as_fn_error $? "conditional \"USE_LIBHYDRA\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
 if test -z "${USE_LIBCHARON_TRUE}" && test -z "${USE_LIBCHARON_FALSE}"; then
   as_fn_error $? "conditional \"USE_LIBCHARON\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -25459,6 +25837,10 @@ if test -z "${USE_PYTHON_EGGS_TRUE}" && test -z "${USE_PYTHON_EGGS_FALSE}"; then
   as_fn_error $? "conditional \"USE_PYTHON_EGGS\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${USE_PERL_CPAN_TRUE}" && test -z "${USE_PERL_CPAN_FALSE}"; then
+  as_fn_error $? "conditional \"USE_PERL_CPAN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${USE_PY_TEST_TRUE}" && test -z "${USE_PY_TEST_FALSE}"; then
   as_fn_error $? "conditional \"USE_PY_TEST\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -25860,7 +26242,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by strongSwan $as_me 5.3.5, which was
+This file was extended by strongSwan $as_me 5.4.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -25926,7 +26308,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-strongSwan config.status 5.3.5
+strongSwan config.status 5.4.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -26399,11 +26781,6 @@ do
     "src/libstrongswan/plugins/bliss/tests/Makefile") CONFIG_FILES="$CONFIG_FILES src/libstrongswan/plugins/bliss/tests/Makefile" ;;
     "src/libstrongswan/plugins/test_vectors/Makefile") CONFIG_FILES="$CONFIG_FILES src/libstrongswan/plugins/test_vectors/Makefile" ;;
     "src/libstrongswan/tests/Makefile") CONFIG_FILES="$CONFIG_FILES src/libstrongswan/tests/Makefile" ;;
-    "src/libhydra/Makefile") CONFIG_FILES="$CONFIG_FILES src/libhydra/Makefile" ;;
-    "src/libhydra/plugins/kernel_netlink/Makefile") CONFIG_FILES="$CONFIG_FILES src/libhydra/plugins/kernel_netlink/Makefile" ;;
-    "src/libhydra/plugins/kernel_pfkey/Makefile") CONFIG_FILES="$CONFIG_FILES src/libhydra/plugins/kernel_pfkey/Makefile" ;;
-    "src/libhydra/plugins/kernel_pfroute/Makefile") CONFIG_FILES="$CONFIG_FILES src/libhydra/plugins/kernel_pfroute/Makefile" ;;
-    "src/libhydra/tests/Makefile") CONFIG_FILES="$CONFIG_FILES src/libhydra/tests/Makefile" ;;
     "src/libipsec/Makefile") CONFIG_FILES="$CONFIG_FILES src/libipsec/Makefile" ;;
     "src/libipsec/tests/Makefile") CONFIG_FILES="$CONFIG_FILES src/libipsec/tests/Makefile" ;;
     "src/libsimaka/Makefile") CONFIG_FILES="$CONFIG_FILES src/libsimaka/Makefile" ;;
@@ -26479,6 +26856,9 @@ do
     "src/libcharon/plugins/unity/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/unity/Makefile" ;;
     "src/libcharon/plugins/uci/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/uci/Makefile" ;;
     "src/libcharon/plugins/ha/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/ha/Makefile" ;;
+    "src/libcharon/plugins/kernel_netlink/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/kernel_netlink/Makefile" ;;
+    "src/libcharon/plugins/kernel_pfkey/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/kernel_pfkey/Makefile" ;;
+    "src/libcharon/plugins/kernel_pfroute/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/kernel_pfroute/Makefile" ;;
     "src/libcharon/plugins/kernel_libipsec/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/kernel_libipsec/Makefile" ;;
     "src/libcharon/plugins/kernel_wfp/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/kernel_wfp/Makefile" ;;
     "src/libcharon/plugins/kernel_iph/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/kernel_iph/Makefile" ;;
@@ -26493,12 +26873,14 @@ do
     "src/libcharon/plugins/coupling/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/coupling/Makefile" ;;
     "src/libcharon/plugins/radattr/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/radattr/Makefile" ;;
     "src/libcharon/plugins/osx_attr/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/osx_attr/Makefile" ;;
+    "src/libcharon/plugins/p_cscf/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/p_cscf/Makefile" ;;
     "src/libcharon/plugins/android_dns/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/android_dns/Makefile" ;;
     "src/libcharon/plugins/android_log/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/android_log/Makefile" ;;
     "src/libcharon/plugins/maemo/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/maemo/Makefile" ;;
     "src/libcharon/plugins/stroke/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/stroke/Makefile" ;;
     "src/libcharon/plugins/vici/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/vici/Makefile" ;;
     "src/libcharon/plugins/vici/ruby/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/vici/ruby/Makefile" ;;
+    "src/libcharon/plugins/vici/perl/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/vici/perl/Makefile" ;;
     "src/libcharon/plugins/vici/python/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/vici/python/Makefile" ;;
     "src/libcharon/plugins/updown/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/updown/Makefile" ;;
     "src/libcharon/plugins/dhcp/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/dhcp/Makefile" ;;
@@ -27923,8 +28305,6 @@ $as_echo "-----------------------------------------------------" >&6; }
 $as_echo "libstrongswan:$s_plugins" >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: libcharon:    $c_plugins" >&5
 $as_echo "libcharon:    $c_plugins" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: libhydra:     $h_plugins" >&5
-$as_echo "libhydra:     $h_plugins" >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: libtnccs:     $t_plugins" >&5
 $as_echo "libtnccs:     $t_plugins" >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5
diff --git a/configure.ac b/configure.ac
index ea6bddb..9486907 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,7 +19,7 @@
 #  initialize & set some vars
 # ============================
 
-AC_INIT([strongSwan],[5.3.5])
+AC_INIT([strongSwan],[5.4.0])
 AM_INIT_AUTOMAKE(m4_esyscmd([
 	echo tar-ustar
 	echo subdir-objects
@@ -221,13 +221,14 @@ ARG_DISBL_SET([stroke],         [disable charons stroke configuration backend.])
 ARG_ENABL_SET([smp],            [enable SMP configuration and control interface. Requires libxml.])
 ARG_ENABL_SET([sql],            [enable SQL database configuration backend.])
 ARG_ENABL_SET([uci],            [enable OpenWRT UCI configuration plugin.])
-ARG_ENABL_SET([vici],           [enable strongSwan IKE generic IPC interface plugin.])
+ARG_DISBL_SET([vici],           [disable strongSwan IKE generic IPC interface plugin.])
 # attribute provider/consumer plugins
 ARG_ENABL_SET([android-dns],    [enable Android specific DNS handler.])
 ARG_DISBL_SET([attr],           [disable strongswan.conf based configuration attribute plugin.])
 ARG_ENABL_SET([attr-sql],       [enable SQL based configuration attribute plugin.])
 ARG_ENABL_SET([dhcp],           [enable DHCP based attribute provider plugin.])
 ARG_ENABL_SET([osx-attr],       [enable OS X SystemConfiguration attribute handler.])
+ARG_ENABL_SET([p-cscf],         [enable plugin to request P-CSCF server addresses from an ePDG.])
 ARG_DISBL_SET([resolve],        [disable resolve DNS handler plugin.])
 ARG_ENABL_SET([unity],          [enables Cisco Unity extension plugin.])
 # TNC modules/plugins
@@ -284,7 +285,7 @@ ARG_DISBL_SET([scepclient],     [disable SCEP client tool.])
 ARG_DISBL_SET([scripts],        [disable additional utilities (found in directory scripts).])
 ARG_ENABL_SET([svc],            [enable charon Windows service.])
 ARG_ENABL_SET([systemd],        [enable systemd specific IKE daemon charon-systemd.])
-ARG_ENABL_SET([swanctl],        [enable swanctl configuration and control tool.])
+ARG_DISBL_SET([swanctl],        [disable swanctl configuration and control tool.])
 ARG_ENABL_SET([tkm],            [enable Trusted Key Manager support.])
 # optional features
 ARG_ENABL_SET([bfd-backtraces], [use binutils libbfd to resolve backtraces for memory leaks and segfaults.])
@@ -299,10 +300,13 @@ ARG_ENABL_SET([ruby-gems],      [enable build of provided ruby gems.])
 ARG_ENABL_SET([ruby-gems-install],[enable installation of provided ruby gems.])
 ARG_ENABL_SET([python-eggs],    [enable build of provided python eggs.])
 ARG_ENABL_SET([python-eggs-install],[enable installation of provided python eggs.])
+ARG_ENABL_SET([perl-cpan],      [enable build of provided perl CPAN module.])
+ARG_ENABL_SET([perl-cpan-install],[enable installation of provided CPAN module.])
 # compile options
 ARG_ENABL_SET([coverage],       [enable lcov coverage report generation.])
 ARG_ENABL_SET([leak-detective], [enable malloc hooks to find memory leaks.])
 ARG_ENABL_SET([lock-profiler],  [enable lock/mutex profiling code.])
+ARG_ENABL_SET([log-thread-ids], [use thread ID, if available, instead of an incremented value starting from 1, to identify threads.])
 ARG_ENABL_SET([monolithic],     [build monolithic version of libstrongswan that includes all enabled plugins. Similarly, the plugins of charon are assembled in libcharon.])
 
 # ===================================
@@ -447,6 +451,10 @@ if test x$python_eggs_install = xtrue; then
 	python_eggs=true
 fi
 
+if test x$perl_cpan_install = xtrue; then
+	perl_cpan=true
+fi
+
 # ===========================================
 #  check required libraries and header files
 # ===========================================
@@ -935,13 +943,16 @@ if test x$systemd = xtrue; then
 		AC_MSG_ERROR([not found (try --with-systemdsystemunitdir)])
 	fi
 
-	PKG_CHECK_MODULES(systemd_daemon, [libsystemd-daemon])
-	AC_SUBST(systemd_daemon_CFLAGS)
-	AC_SUBST(systemd_daemon_LIBS)
-
-	PKG_CHECK_MODULES(systemd_journal, [libsystemd-journal])
-	AC_SUBST(systemd_journal_CFLAGS)
-	AC_SUBST(systemd_journal_LIBS)
+	PKG_CHECK_MODULES(systemd, [libsystemd >= 209],
+		[AC_SUBST(systemd_CFLAGS)
+		 AC_SUBST(systemd_LIBS)],
+		[PKG_CHECK_MODULES(systemd_daemon, [libsystemd-daemon])
+		 AC_SUBST(systemd_daemon_CFLAGS)
+		 AC_SUBST(systemd_daemon_LIBS)
+		 PKG_CHECK_MODULES(systemd_journal, [libsystemd-journal])
+		 AC_SUBST(systemd_journal_CFLAGS)
+		 AC_SUBST(systemd_journal_LIBS)]
+	)
 fi
 
 if test x$tss = xtrousers; then
@@ -1063,7 +1074,8 @@ if test x$sqlite = xtrue; then
 fi
 
 if test x$openssl = xtrue; then
-	AC_CHECK_LIB([$openssl_lib],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([OpenSSL lib$openssl_lib not found])],[])
+	AC_CHECK_LIB([$openssl_lib],[main],[LIBS="$LIBS"],
+				 [AC_MSG_ERROR([OpenSSL lib$openssl_lib not found])],[$DLLIB])
 	AC_CHECK_HEADER([openssl/evp.h],,[AC_MSG_ERROR([OpenSSL header openssl/evp.h not found!])])
 fi
 
@@ -1247,6 +1259,8 @@ if test x$python_eggs = xtrue; then
 fi
 AM_CONDITIONAL(PYTHON_EGGS_INSTALL, [test "x$python_eggs_install" = xtrue])
 
+AM_CONDITIONAL(PERL_CPAN_INSTALL, [test "x$perl_cpan_install" = xtrue])
+
 # ===============================================
 #  collect plugin list for strongSwan components
 # ===============================================
@@ -1268,9 +1282,8 @@ cmd_plugins=
 aikgen_plugins=
 
 # location specific lists for checksumming,
-# for src/libcharon, src/libhydra, src/libstrongswan and src/libtnccs
+# for src/libcharon, src/libstrongswan and src/libtnccs
 c_plugins=
-h_plugins=
 s_plugins=
 t_plugins=
 
@@ -1283,9 +1296,9 @@ ADD_PLUGIN([aes],                  [s charon scepclient pki scripts nm cmd])
 ADD_PLUGIN([des],                  [s charon scepclient pki scripts nm cmd])
 ADD_PLUGIN([blowfish],             [s charon scepclient pki scripts nm cmd])
 ADD_PLUGIN([rc2],                  [s charon scepclient pki scripts nm cmd])
-ADD_PLUGIN([sha1],                 [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen])
 ADD_PLUGIN([sha2],                 [s charon scepclient pki scripts medsrv attest nm cmd aikgen])
 ADD_PLUGIN([sha3],                 [s charon scepclient pki scripts medsrv attest nm cmd aikgen])
+ADD_PLUGIN([sha1],                 [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen])
 ADD_PLUGIN([md4],                  [s charon scepclient pki nm cmd])
 ADD_PLUGIN([md5],                  [s charon scepclient pki scripts attest nm cmd aikgen])
 ADD_PLUGIN([rdrand],               [s charon scepclient pki scripts medsrv attest nm cmd aikgen])
@@ -1335,9 +1348,9 @@ ADD_PLUGIN([load-tester],          [c charon])
 ADD_PLUGIN([kernel-libipsec],      [c charon cmd])
 ADD_PLUGIN([kernel-wfp],           [c charon])
 ADD_PLUGIN([kernel-iph],           [c charon])
-ADD_PLUGIN([kernel-pfkey],         [h charon starter nm cmd])
-ADD_PLUGIN([kernel-pfroute],       [h charon starter nm cmd])
-ADD_PLUGIN([kernel-netlink],       [h charon starter nm cmd])
+ADD_PLUGIN([kernel-pfkey],         [c charon starter nm cmd])
+ADD_PLUGIN([kernel-pfroute],       [c charon starter nm cmd])
+ADD_PLUGIN([kernel-netlink],       [c charon starter nm cmd])
 ADD_PLUGIN([resolve],              [c charon cmd])
 ADD_PLUGIN([socket-default],       [c charon nm cmd])
 ADD_PLUGIN([socket-dynamic],       [c charon cmd])
@@ -1384,6 +1397,7 @@ ADD_PLUGIN([medsrv],               [c charon])
 ADD_PLUGIN([medcli],               [c charon])
 ADD_PLUGIN([dhcp],                 [c charon])
 ADD_PLUGIN([osx-attr],             [c charon cmd])
+ADD_PLUGIN([p-cscf],               [c charon cmd])
 ADD_PLUGIN([android-dns],          [c charon])
 ADD_PLUGIN([android-log],          [c charon])
 ADD_PLUGIN([ha],                   [c charon])
@@ -1488,6 +1502,7 @@ AM_CONDITIONAL(USE_MEDSRV, test x$medsrv = xtrue)
 AM_CONDITIONAL(USE_MEDCLI, test x$medcli = xtrue)
 AM_CONDITIONAL(USE_UCI, test x$uci = xtrue)
 AM_CONDITIONAL(USE_OSX_ATTR, test x$osx_attr = xtrue)
+AM_CONDITIONAL(USE_P_CSCF, test x$p_cscf = xtrue)
 AM_CONDITIONAL(USE_ANDROID_DNS, test x$android_dns = xtrue)
 AM_CONDITIONAL(USE_ANDROID_LOG, test x$android_log = xtrue)
 AM_CONDITIONAL(USE_MAEMO, test x$maemo = xtrue)
@@ -1499,6 +1514,9 @@ AM_CONDITIONAL(USE_UPDOWN, test x$updown = xtrue)
 AM_CONDITIONAL(USE_DHCP, test x$dhcp = xtrue)
 AM_CONDITIONAL(USE_LOAD_TESTER, test x$load_tester = xtrue)
 AM_CONDITIONAL(USE_HA, test x$ha = xtrue)
+AM_CONDITIONAL(USE_KERNEL_NETLINK, test x$kernel_netlink = xtrue)
+AM_CONDITIONAL(USE_KERNEL_PFKEY, test x$kernel_pfkey = xtrue)
+AM_CONDITIONAL(USE_KERNEL_PFROUTE, test x$kernel_pfroute = xtrue)
 AM_CONDITIONAL(USE_KERNEL_LIBIPSEC, test x$kernel_libipsec = xtrue)
 AM_CONDITIONAL(USE_KERNEL_WFP, test x$kernel_wfp = xtrue)
 AM_CONDITIONAL(USE_KERNEL_IPH, test x$kernel_iph = xtrue)
@@ -1566,12 +1584,6 @@ AM_CONDITIONAL(USE_RESOLVE, test x$resolve = xtrue)
 AM_CONDITIONAL(USE_ATTR, test x$attr = xtrue)
 AM_CONDITIONAL(USE_ATTR_SQL, test x$attr_sql = xtrue)
 
-#  hydra plugins
-# ---------------
-AM_CONDITIONAL(USE_KERNEL_NETLINK, test x$kernel_netlink = xtrue)
-AM_CONDITIONAL(USE_KERNEL_PFKEY, test x$kernel_pfkey = xtrue)
-AM_CONDITIONAL(USE_KERNEL_PFROUTE, test x$kernel_pfroute = xtrue)
-
 #  other options
 # ---------------
 AM_CONDITIONAL(USE_LEAK_DETECTIVE, test x$leak_detective = xtrue)
@@ -1593,7 +1605,6 @@ AM_CONDITIONAL(USE_SCEPCLIENT, test x$scepclient = xtrue)
 AM_CONDITIONAL(USE_SCRIPTS, test x$scripts = xtrue)
 AM_CONDITIONAL(USE_CONFTEST, test x$conftest = xtrue)
 AM_CONDITIONAL(USE_LIBSTRONGSWAN, test x$charon = xtrue -o x$pki = xtrue -o x$scepclient = xtrue -o x$conftest = xtrue -o x$fast = xtrue -o x$imcv = xtrue -o x$nm = xtrue -o x$tkm = xtrue -o x$cmd = xtrue -o x$tls = xtrue -o x$tnc_tnccs = xtrue -o x$aikgen = xtrue -o x$svc = xtrue -o x$systemd = xtrue)
-AM_CONDITIONAL(USE_LIBHYDRA, test x$charon = xtrue -o x$nm = xtrue -o x$tkm = xtrue -o x$cmd = xtrue -o x$svc = xtrue -o x$systemd = xtrue)
 AM_CONDITIONAL(USE_LIBCHARON, test x$charon = xtrue -o x$conftest = xtrue -o x$nm = xtrue -o x$tkm = xtrue -o x$cmd = xtrue -o x$svc = xtrue -o x$systemd = xtrue)
 AM_CONDITIONAL(USE_LIBIPSEC, test x$libipsec = xtrue)
 AM_CONDITIONAL(USE_LIBTNCIF, test x$tnc_tnccs = xtrue -o x$imcv = xtrue)
@@ -1622,6 +1633,7 @@ AM_CONDITIONAL(USE_SYSTEMD, test x$systemd = xtrue)
 AM_CONDITIONAL(USE_LEGACY_SYSTEMD, test -n "$systemdsystemunitdir" -a "x$systemdsystemunitdir" != xno)
 AM_CONDITIONAL(USE_RUBY_GEMS, test x$ruby_gems = xtrue)
 AM_CONDITIONAL(USE_PYTHON_EGGS, test x$python_eggs = xtrue)
+AM_CONDITIONAL(USE_PERL_CPAN, test x$perl_cpan = xtrue)
 AM_CONDITIONAL(USE_PY_TEST, test "x$PY_TEST" != x)
 
 # ========================
@@ -1634,6 +1646,9 @@ fi
 if test x$capabilities = xlibcap -o x$capabilities = xnative; then
 	AC_DEFINE([CAPABILITIES], [], [capability dropping support])
 fi
+if test x$log_thread_ids = xtrue; then
+	AC_DEFINE([USE_THREAD_IDS], [], [use thread ID for thread identification, if available])
+fi
 if test x$monolithic = xtrue; then
 	AC_DEFINE([MONOLITHIC], [], [monolithic build embedding plugins])
 fi
@@ -1735,11 +1750,6 @@ AC_CONFIG_FILES([
 	src/libstrongswan/plugins/bliss/tests/Makefile
 	src/libstrongswan/plugins/test_vectors/Makefile
 	src/libstrongswan/tests/Makefile
-	src/libhydra/Makefile
-	src/libhydra/plugins/kernel_netlink/Makefile
-	src/libhydra/plugins/kernel_pfkey/Makefile
-	src/libhydra/plugins/kernel_pfroute/Makefile
-	src/libhydra/tests/Makefile
 	src/libipsec/Makefile
 	src/libipsec/tests/Makefile
 	src/libsimaka/Makefile
@@ -1815,6 +1825,9 @@ AC_CONFIG_FILES([
 	src/libcharon/plugins/unity/Makefile
 	src/libcharon/plugins/uci/Makefile
 	src/libcharon/plugins/ha/Makefile
+	src/libcharon/plugins/kernel_netlink/Makefile
+	src/libcharon/plugins/kernel_pfkey/Makefile
+	src/libcharon/plugins/kernel_pfroute/Makefile
 	src/libcharon/plugins/kernel_libipsec/Makefile
 	src/libcharon/plugins/kernel_wfp/Makefile
 	src/libcharon/plugins/kernel_iph/Makefile
@@ -1829,12 +1842,14 @@ AC_CONFIG_FILES([
 	src/libcharon/plugins/coupling/Makefile
 	src/libcharon/plugins/radattr/Makefile
 	src/libcharon/plugins/osx_attr/Makefile
+	src/libcharon/plugins/p_cscf/Makefile
 	src/libcharon/plugins/android_dns/Makefile
 	src/libcharon/plugins/android_log/Makefile
 	src/libcharon/plugins/maemo/Makefile
 	src/libcharon/plugins/stroke/Makefile
 	src/libcharon/plugins/vici/Makefile
 	src/libcharon/plugins/vici/ruby/Makefile
+	src/libcharon/plugins/vici/perl/Makefile
 	src/libcharon/plugins/vici/python/Makefile
 	src/libcharon/plugins/updown/Makefile
 	src/libcharon/plugins/dhcp/Makefile
@@ -1908,6 +1923,5 @@ AC_MSG_RESULT([-----------------------------------------------------])
 
 AC_MSG_RESULT([libstrongswan:$s_plugins])
 AC_MSG_RESULT([libcharon:    $c_plugins])
-AC_MSG_RESULT([libhydra:     $h_plugins])
 AC_MSG_RESULT([libtnccs:     $t_plugins])
 AC_MSG_RESULT([])
diff --git a/init/Makefile.in b/init/Makefile.in
index 883d424..72ee059 100644
--- a/init/Makefile.in
+++ b/init/Makefile.in
@@ -391,6 +391,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/init/systemd-swanctl/Makefile.in b/init/systemd-swanctl/Makefile.in
index 28cedbd..0c5f5ce 100644
--- a/init/systemd-swanctl/Makefile.in
+++ b/init/systemd-swanctl/Makefile.in
@@ -359,6 +359,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/init/systemd-swanctl/strongswan-swanctl.service.in b/init/systemd-swanctl/strongswan-swanctl.service.in
index 818d352..944101f 100644
--- a/init/systemd-swanctl/strongswan-swanctl.service.in
+++ b/init/systemd-swanctl/strongswan-swanctl.service.in
@@ -7,3 +7,6 @@ Type=notify
 ExecStart=@SBINDIR@/charon-systemd
 ExecStartPost=@SBINDIR@/swanctl --load-all --noprompt
 ExecReload=@SBINDIR@/swanctl --reload
+
+[Install]
+WantedBy=multi-user.target
diff --git a/init/systemd/Makefile.in b/init/systemd/Makefile.in
index 808023e..ab7d647 100644
--- a/init/systemd/Makefile.in
+++ b/init/systemd/Makefile.in
@@ -359,6 +359,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/man/Makefile.in b/man/Makefile.in
index 5013610..5f621c2 100644
--- a/man/Makefile.in
+++ b/man/Makefile.in
@@ -365,6 +365,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/man/ipsec.conf.5.in b/man/ipsec.conf.5.in
index 61804c8..54440c0 100644
--- a/man/ipsec.conf.5.in
+++ b/man/ipsec.conf.5.in
@@ -402,7 +402,7 @@ or
 keyword may be used, AH+ESP bundles are not supported.
 
 Defaults to
-.BR aes128-sha1,3des-sha1 .
+.BR aes128-sha256 .
 The daemon adds its extensive default proposal to this default
 or the configured value.  To restrict it to the configured proposal an
 exclamation mark
@@ -453,7 +453,7 @@ if required.
 .BR ike " = <cipher suites>"
 comma-separated list of IKE/ISAKMP SA encryption/authentication algorithms
 to be used, e.g.
-.BR aes128-sha1-modp2048 .
+.BR aes128-sha256-modp3072 .
 The notation is
 .BR encryption-integrity[-prf]-dhgroup .
 If no PRF is given, the algorithms defined for integrity are used for the PRF.
@@ -466,10 +466,10 @@ or
 .BR prfaesxcbc ).
 .br
 In IKEv2, multiple algorithms and proposals may be included, such as
-.BR aes128-aes256-sha1-modp1536-modp2048,3des-sha1-md5-modp1024 .
+.BR aes128-aes256-sha1-modp3072-modp2048,3des-sha1-md5-modp1024 .
 
 Defaults to
-.BR aes128-sha1-modp2048,3des-sha1-modp1536 .
+.BR aes128-sha256-modp3072 .
 The daemon adds its extensive default proposal to this
 default or the configured value.  To restrict it to the configured proposal an
 exclamation mark
@@ -587,18 +587,23 @@ or a key strength definition (for example
 or
 .BR rsa-2048-ecdsa-256-sha256-sha384-sha512 ).
 Unless disabled in
-.BR strongswan.conf (5)
-such key types and hash algorithms are also applied as constraints against IKEv2
+.BR strongswan.conf (5),
+or explicit IKEv2 signature constraints are configured (see below), such key
+types and hash algorithms are also applied as constraints against IKEv2
 signature authentication schemes used by the remote side.
 
 If both peers support RFC 7427 ("Signature Authentication in IKEv2") specific
 hash algorithms to be used during IKEv2 authentication may be configured.
-The syntax is the same as above. For example, with
-.B pubkey-sha384-sha256
+The syntax is the same as above, but with ike: prefix. For example, with
+.B ike:pubkey-sha384-sha256
 a public key signature scheme with either SHA-384 or SHA-256 would get used for
 authentication, in that order and depending on the hash algorithms supported by
 the peer.  If no specific hash algorithms are configured, the default is to
 prefer an algorithm that matches or exceeds the strength of the signature key.
+If no constraints with ike: prefix are configured any signature scheme
+constraint (without ike: prefix) will also apply to IKEv2 authentication, unless
+this is disabled in
+.BR strongswan.conf (5).
 
 For
 .BR eap ,
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
index bdb8e5f..15e9006 100644
--- a/scripts/Makefile.in
+++ b/scripts/Makefile.in
@@ -474,6 +474,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/Makefile.am b/src/Makefile.am
index 9608a3a..a9df10c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,10 +4,6 @@ if USE_LIBSTRONGSWAN
   SUBDIRS += libstrongswan
 endif
 
-if USE_LIBHYDRA
-  SUBDIRS += libhydra
-endif
-
 if USE_LIBIPSEC
   SUBDIRS += libipsec
 endif
diff --git a/src/Makefile.in b/src/Makefile.in
index 7596e7e..1d012fb 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -78,39 +78,38 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 @USE_LIBSTRONGSWAN_TRUE at am__append_1 = libstrongswan
- at USE_LIBHYDRA_TRUE@am__append_2 = libhydra
- at USE_LIBIPSEC_TRUE@am__append_3 = libipsec
- at USE_SIMAKA_TRUE@am__append_4 = libsimaka
- at USE_TLS_TRUE@am__append_5 = libtls
- at USE_RADIUS_TRUE@am__append_6 = libradius
- at USE_LIBTNCIF_TRUE@am__append_7 = libtncif
- at USE_LIBTNCCS_TRUE@am__append_8 = libtnccs
- at USE_LIBPTTLS_TRUE@am__append_9 = libpttls
- at USE_IMCV_TRUE@am__append_10 = libimcv
- at USE_LIBCHARON_TRUE@am__append_11 = libcharon
- at USE_FILE_CONFIG_TRUE@am__append_12 = starter
- at USE_IPSEC_SCRIPT_TRUE@am__append_13 = ipsec _copyright
- at USE_CHARON_TRUE@am__append_14 = charon
- at USE_SYSTEMD_TRUE@am__append_15 = charon-systemd
- at USE_NM_TRUE@am__append_16 = charon-nm
- at USE_STROKE_TRUE@am__append_17 = stroke
- at USE_UPDOWN_TRUE@am__append_18 = _updown
- at USE_SCEPCLIENT_TRUE@am__append_19 = scepclient
- at USE_PKI_TRUE@am__append_20 = pki
- at USE_SWANCTL_TRUE@am__append_21 = swanctl
- at USE_CONFTEST_TRUE@am__append_22 = conftest
- at USE_DUMM_TRUE@am__append_23 = dumm
- at USE_FAST_TRUE@am__append_24 = libfast
- at USE_MANAGER_TRUE@am__append_25 = manager
- at USE_MEDSRV_TRUE@am__append_26 = medsrv
- at USE_ATTR_SQL_TRUE@am__append_27 = pool
- at USE_ATTR_SQL_FALSE@@USE_SQL_TRUE at am__append_28 = pool
- at USE_TKM_TRUE@am__append_29 = charon-tkm
- at USE_CMD_TRUE@am__append_30 = charon-cmd
- at USE_SVC_TRUE@am__append_31 = charon-svc
- at USE_LIBPTTLS_TRUE@am__append_32 = pt-tls-client
- at USE_INTEGRITY_TEST_TRUE@am__append_33 = checksum
- at USE_AIKGEN_TRUE@am__append_34 = aikgen
+ at USE_LIBIPSEC_TRUE@am__append_2 = libipsec
+ at USE_SIMAKA_TRUE@am__append_3 = libsimaka
+ at USE_TLS_TRUE@am__append_4 = libtls
+ at USE_RADIUS_TRUE@am__append_5 = libradius
+ at USE_LIBTNCIF_TRUE@am__append_6 = libtncif
+ at USE_LIBTNCCS_TRUE@am__append_7 = libtnccs
+ at USE_LIBPTTLS_TRUE@am__append_8 = libpttls
+ at USE_IMCV_TRUE@am__append_9 = libimcv
+ at USE_LIBCHARON_TRUE@am__append_10 = libcharon
+ at USE_FILE_CONFIG_TRUE@am__append_11 = starter
+ at USE_IPSEC_SCRIPT_TRUE@am__append_12 = ipsec _copyright
+ at USE_CHARON_TRUE@am__append_13 = charon
+ at USE_SYSTEMD_TRUE@am__append_14 = charon-systemd
+ at USE_NM_TRUE@am__append_15 = charon-nm
+ at USE_STROKE_TRUE@am__append_16 = stroke
+ at USE_UPDOWN_TRUE@am__append_17 = _updown
+ at USE_SCEPCLIENT_TRUE@am__append_18 = scepclient
+ at USE_PKI_TRUE@am__append_19 = pki
+ at USE_SWANCTL_TRUE@am__append_20 = swanctl
+ at USE_CONFTEST_TRUE@am__append_21 = conftest
+ at USE_DUMM_TRUE@am__append_22 = dumm
+ at USE_FAST_TRUE@am__append_23 = libfast
+ at USE_MANAGER_TRUE@am__append_24 = manager
+ at USE_MEDSRV_TRUE@am__append_25 = medsrv
+ at USE_ATTR_SQL_TRUE@am__append_26 = pool
+ at USE_ATTR_SQL_FALSE@@USE_SQL_TRUE at am__append_27 = pool
+ at USE_TKM_TRUE@am__append_28 = charon-tkm
+ at USE_CMD_TRUE@am__append_29 = charon-cmd
+ at USE_SVC_TRUE@am__append_30 = charon-svc
+ at USE_LIBPTTLS_TRUE@am__append_31 = pt-tls-client
+ at USE_INTEGRITY_TEST_TRUE@am__append_32 = checksum
+ at USE_AIKGEN_TRUE@am__append_33 = aikgen
 subdir = src
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -184,12 +183,12 @@ am__define_uniq_tagged_files = \
   done | $(am__uniquify_input)`
 ETAGS = etags
 CTAGS = ctags
-DIST_SUBDIRS = . include libstrongswan libhydra libipsec libsimaka \
-	libtls libradius libtncif libtnccs libpttls libimcv libcharon \
-	starter ipsec _copyright charon charon-systemd charon-nm \
-	stroke _updown scepclient pki swanctl conftest dumm libfast \
-	manager medsrv pool charon-tkm charon-cmd charon-svc \
-	pt-tls-client checksum aikgen
+DIST_SUBDIRS = . include libstrongswan libipsec libsimaka libtls \
+	libradius libtncif libtnccs libpttls libimcv libcharon starter \
+	ipsec _copyright charon charon-systemd charon-nm stroke \
+	_updown scepclient pki swanctl conftest dumm libfast manager \
+	medsrv pool charon-tkm charon-cmd charon-svc pt-tls-client \
+	checksum aikgen
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 am__relativize = \
   dir0=`pwd`; \
@@ -428,6 +427,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -451,8 +452,7 @@ SUBDIRS = . include $(am__append_1) $(am__append_2) $(am__append_3) \
 	$(am__append_22) $(am__append_23) $(am__append_24) \
 	$(am__append_25) $(am__append_26) $(am__append_27) \
 	$(am__append_28) $(am__append_29) $(am__append_30) \
-	$(am__append_31) $(am__append_32) $(am__append_33) \
-	$(am__append_34)
+	$(am__append_31) $(am__append_32) $(am__append_33)
 all: all-recursive
 
 .SUFFIXES:
diff --git a/src/_copyright/Makefile.in b/src/_copyright/Makefile.in
index 2a4838c..432bde5 100644
--- a/src/_copyright/Makefile.in
+++ b/src/_copyright/Makefile.in
@@ -382,6 +382,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/_updown/Makefile.in b/src/_updown/Makefile.in
index fe31dff..08fce3e 100644
--- a/src/_updown/Makefile.in
+++ b/src/_updown/Makefile.in
@@ -359,6 +359,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/aikgen/Makefile.in b/src/aikgen/Makefile.in
index 33ed133..8fb9126 100644
--- a/src/aikgen/Makefile.in
+++ b/src/aikgen/Makefile.in
@@ -385,6 +385,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/charon-cmd/Makefile.am b/src/charon-cmd/Makefile.am
index 73df450..1f4033a 100644
--- a/src/charon-cmd/Makefile.am
+++ b/src/charon-cmd/Makefile.am
@@ -12,7 +12,6 @@ charon-cmd.o :	$(top_builddir)/config.status
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_DIR=\"${ipsecdir}\" \
 	-DIPSEC_PIDDIR=\"${piddir}\" \
@@ -20,6 +19,5 @@ AM_CPPFLAGS = \
 
 charon_cmd_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
 	-lm $(PTHREADLIB) $(DLLIB)
diff --git a/src/charon-cmd/Makefile.in b/src/charon-cmd/Makefile.in
index 64dea34..f484102 100644
--- a/src/charon-cmd/Makefile.in
+++ b/src/charon-cmd/Makefile.in
@@ -109,7 +109,6 @@ charon_cmd_OBJECTS = $(am_charon_cmd_OBJECTS)
 am__DEPENDENCIES_1 =
 charon_cmd_DEPENDENCIES =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 AM_V_lt = $(am__v_lt_ at AM_V@)
@@ -419,6 +418,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -442,7 +443,6 @@ charon_cmd_SOURCES = \
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_DIR=\"${ipsecdir}\" \
 	-DIPSEC_PIDDIR=\"${piddir}\" \
@@ -450,7 +450,6 @@ AM_CPPFLAGS = \
 
 charon_cmd_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
 	-lm $(PTHREADLIB) $(DLLIB)
 
diff --git a/src/charon-cmd/charon-cmd.c b/src/charon-cmd/charon-cmd.c
index d3b31cc..f350198 100644
--- a/src/charon-cmd/charon-cmd.c
+++ b/src/charon-cmd/charon-cmd.c
@@ -26,7 +26,6 @@
 #include <errno.h>
 
 #include <library.h>
-#include <hydra.h>
 #include <daemon.h>
 #include <utils/backtrace.h>
 #include <threading/thread.h>
@@ -330,11 +329,6 @@ int main(int argc, char *argv[])
 			exit(SS_RC_DAEMON_INTEGRITY);
 		}
 	}
-	atexit(libhydra_deinit);
-	if (!libhydra_init())
-	{
-		exit(SS_RC_INITIALIZATION_FAILED);
-	}
 	atexit(libcharon_deinit);
 	if (!libcharon_init())
 	{
diff --git a/src/charon-nm/Makefile.am b/src/charon-nm/Makefile.am
index d3630ff..b6f0c8b 100644
--- a/src/charon-nm/Makefile.am
+++ b/src/charon-nm/Makefile.am
@@ -9,7 +9,6 @@ charon_nm_SOURCES = \
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_DIR=\"${ipsecdir}\" \
 	-DIPSEC_PIDDIR=\"${piddir}\" \
@@ -21,6 +20,5 @@ AM_CFLAGS = \
 
 charon_nm_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
 	-lm $(PTHREADLIB) $(DLLIB) ${nm_LIBS}
diff --git a/src/charon-nm/Makefile.in b/src/charon-nm/Makefile.in
index 82f6fbc..490a080 100644
--- a/src/charon-nm/Makefile.in
+++ b/src/charon-nm/Makefile.in
@@ -109,7 +109,6 @@ charon_nm_OBJECTS = $(am_charon_nm_OBJECTS)
 am__DEPENDENCIES_1 =
 charon_nm_DEPENDENCIES =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1)
@@ -390,6 +389,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -412,7 +413,6 @@ charon_nm_SOURCES = \
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_DIR=\"${ipsecdir}\" \
 	-DIPSEC_PIDDIR=\"${piddir}\" \
@@ -424,7 +424,6 @@ AM_CFLAGS = \
 
 charon_nm_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
 	-lm $(PTHREADLIB) $(DLLIB) ${nm_LIBS}
 
diff --git a/src/charon-nm/charon-nm.c b/src/charon-nm/charon-nm.c
index fb090e5..cbbed7a 100644
--- a/src/charon-nm/charon-nm.c
+++ b/src/charon-nm/charon-nm.c
@@ -20,7 +20,6 @@
 #include <unistd.h>
 #include <errno.h>
 
-#include <hydra.h>
 #include <daemon.h>
 
 #include <library.h>
@@ -177,14 +176,6 @@ int main(int argc, char *argv[])
 		exit(SS_RC_DAEMON_INTEGRITY);
 	}
 
-	if (!libhydra_init())
-	{
-		dbg_syslog(DBG_DMN, 1, "initialization failed - aborting charon-nm");
-		libhydra_deinit();
-		library_deinit();
-		exit(SS_RC_INITIALIZATION_FAILED);
-	}
-
 	if (!libcharon_init())
 	{
 		dbg_syslog(DBG_DMN, 1, "initialization failed - aborting charon-nm");
@@ -212,7 +203,6 @@ int main(int argc, char *argv[])
 	{
 		DBG1(DBG_DMN, "integrity tests enabled:");
 		DBG1(DBG_DMN, "lib    'libstrongswan': passed file and segment integrity tests");
-		DBG1(DBG_DMN, "lib    'libhydra': passed file and segment integrity tests");
 		DBG1(DBG_DMN, "lib    'libcharon': passed file and segment integrity tests");
 		DBG1(DBG_DMN, "daemon 'charon-nm': passed file integrity test");
 	}
@@ -260,7 +250,6 @@ int main(int argc, char *argv[])
 
 deinit:
 	libcharon_deinit();
-	libhydra_deinit();
 	library_deinit();
 	return status;
 }
diff --git a/src/charon-svc/Makefile.am b/src/charon-svc/Makefile.am
index ecccf02..c91ad08 100644
--- a/src/charon-svc/Makefile.am
+++ b/src/charon-svc/Makefile.am
@@ -6,11 +6,9 @@ charon-svc.o :	$(top_builddir)/config.status
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DPLUGINS=\""${charon_plugins}\""
 
 charon_svc_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la
diff --git a/src/charon-svc/Makefile.in b/src/charon-svc/Makefile.in
index 1c0a405..4f9143d 100644
--- a/src/charon-svc/Makefile.in
+++ b/src/charon-svc/Makefile.in
@@ -105,7 +105,6 @@ am_charon_svc_OBJECTS = charon-svc.$(OBJEXT)
 charon_svc_OBJECTS = $(am_charon_svc_OBJECTS)
 charon_svc_DEPENDENCIES =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la
 AM_V_lt = $(am__v_lt_ at AM_V@)
 am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
@@ -384,6 +383,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -400,13 +401,11 @@ xml_LIBS = @xml_LIBS@
 charon_svc_SOURCES = charon-svc.c
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DPLUGINS=\""${charon_plugins}\""
 
 charon_svc_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la
 
 all: all-am
diff --git a/src/charon-svc/charon-svc.c b/src/charon-svc/charon-svc.c
index 03cbdb8..823b366 100644
--- a/src/charon-svc/charon-svc.c
+++ b/src/charon-svc/charon-svc.c
@@ -14,7 +14,6 @@
  */
 
 #include <library.h>
-#include <hydra.h>
 #include <daemon.h>
 
 #include <utils/backtrace.h>
@@ -190,6 +189,15 @@ static int service_wait()
 }
 
 /**
+ * Add namespace alias
+ */
+static void __attribute__ ((constructor))register_namespace()
+{
+	/* inherit settings from charon */
+	library_add_namespace("charon");
+}
+
+/**
  * Initialize and run charon using a wait function
  */
 static void init_and_run(DWORD dwArgc, LPTSTR *lpszArgv, int (*wait)())
@@ -210,28 +218,22 @@ static void init_and_run(DWORD dwArgc, LPTSTR *lpszArgv, int (*wait)())
 		if (library_init(NULL, SERVICE_NAME))
 		{
 			update_status(SERVICE_START_PENDING);
-			if (libhydra_init())
+			if (libcharon_init())
 			{
+				charon->load_loggers(charon, levels, TRUE);
+				print_version();
 				update_status(SERVICE_START_PENDING);
-				if (libcharon_init())
+				if (charon->initialize(charon, PLUGINS))
 				{
-					charon->load_loggers(charon, levels, TRUE);
-					print_version();
 					update_status(SERVICE_START_PENDING);
-					if (charon->initialize(charon, PLUGINS))
-					{
-						update_status(SERVICE_START_PENDING);
-						lib->plugins->status(lib->plugins, LEVEL_CTRL);
+					lib->plugins->status(lib->plugins, LEVEL_CTRL);
 
-						charon->start(charon);
+					charon->start(charon);
 
-						status.dwWin32ExitCode = wait();
-					}
-					update_status(SERVICE_STOP_PENDING);
-					libcharon_deinit();
+					status.dwWin32ExitCode = wait();
 				}
 				update_status(SERVICE_STOP_PENDING);
-				libhydra_deinit();
+				libcharon_deinit();
 			}
 			update_status(SERVICE_STOP_PENDING);
 			library_deinit();
diff --git a/src/charon-systemd/Makefile.am b/src/charon-systemd/Makefile.am
index 1b9ac15..9942a36 100644
--- a/src/charon-systemd/Makefile.am
+++ b/src/charon-systemd/Makefile.am
@@ -7,13 +7,11 @@ charon-systemd.o :	$(top_builddir)/config.status
 
 charon_systemd_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
-	$(systemd_daemon_CFLAGS) $(systemd_journal_CFLAGS) \
+	$(systemd_CFLAGS) $(systemd_daemon_CFLAGS) $(systemd_journal_CFLAGS) \
 	-DPLUGINS=\""${charon_plugins}\""
 
 charon_systemd_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
-	$(systemd_daemon_LIBS) $(systemd_journal_LIBS) -lm $(PTHREADLIB) $(DLLIB)
+	$(systemd_LIBS) $(systemd_daemon_LIBS) $(systemd_journal_LIBS) -lm $(PTHREADLIB) $(DLLIB)
diff --git a/src/charon-systemd/Makefile.in b/src/charon-systemd/Makefile.in
index d6e1c47..b4f624d 100644
--- a/src/charon-systemd/Makefile.in
+++ b/src/charon-systemd/Makefile.in
@@ -106,10 +106,10 @@ charon_systemd_OBJECTS = $(am_charon_systemd_OBJECTS)
 am__DEPENDENCIES_1 =
 charon_systemd_DEPENDENCIES =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 AM_V_lt = $(am__v_lt_ at AM_V@)
 am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
 am__v_lt_0 = --silent
@@ -387,6 +387,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -405,16 +407,14 @@ charon-systemd.c
 
 charon_systemd_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
-	$(systemd_daemon_CFLAGS) $(systemd_journal_CFLAGS) \
+	$(systemd_CFLAGS) $(systemd_daemon_CFLAGS) $(systemd_journal_CFLAGS) \
 	-DPLUGINS=\""${charon_plugins}\""
 
 charon_systemd_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
-	$(systemd_daemon_LIBS) $(systemd_journal_LIBS) -lm $(PTHREADLIB) $(DLLIB)
+	$(systemd_LIBS) $(systemd_daemon_LIBS) $(systemd_journal_LIBS) -lm $(PTHREADLIB) $(DLLIB)
 
 all: all-am
 
diff --git a/src/charon-systemd/charon-systemd.c b/src/charon-systemd/charon-systemd.c
index 4286cde..5c7bbd7 100644
--- a/src/charon-systemd/charon-systemd.c
+++ b/src/charon-systemd/charon-systemd.c
@@ -31,7 +31,6 @@
 #include <systemd/sd-daemon.h>
 #include <systemd/sd-journal.h>
 
-#include <hydra.h>
 #include <daemon.h>
 
 #include <library.h>
@@ -326,6 +325,15 @@ static plugin_feature_t features[] = {
 };
 
 /**
+ * Add namespace alias
+ */
+static void __attribute__ ((constructor))register_namespace()
+{
+	/* inherit settings from charon */
+	library_add_namespace("charon");
+}
+
+/**
  * Main function, starts the daemon.
  */
 int main(int argc, char *argv[])
@@ -355,12 +363,6 @@ int main(int argc, char *argv[])
 		sd_notifyf(0, "STATUS=integrity check of charon-systemd failed");
 		return SS_RC_INITIALIZATION_FAILED;
 	}
-	atexit(libhydra_deinit);
-	if (!libhydra_init())
-	{
-		sd_notifyf(0, "STATUS=libhydra initialization failed");
-		return SS_RC_INITIALIZATION_FAILED;
-	}
 	atexit(libcharon_deinit);
 	if (!libcharon_init())
 	{
diff --git a/src/charon-tkm/Makefile.am b/src/charon-tkm/Makefile.am
index d2b81a3..ad54eaf 100644
--- a/src/charon-tkm/Makefile.am
+++ b/src/charon-tkm/Makefile.am
@@ -4,15 +4,13 @@ OBJ = $(abs_top_builddir)/src
 AM_CPPFLAGS = \
 	-include $(abs_top_builddir)/config.h \
 	-I$(SRC)/libstrongswan \
-	-I$(SRC)/libhydra \
 	-I$(SRC)/libcharon
 
 LIBLD = \
 	-L$(OBJ)/libstrongswan/.libs \
-	-L$(OBJ)/libhydra/.libs \
 	-L$(OBJ)/libcharon/.libs
-LIBPT = $(OBJ)/libstrongswan/.libs:$(OBJ)/libhydra/.libs:$(OBJ)/libcharon/.libs
-LIBFL = -lstrongswan -lhydra -lcharon
+LIBPT = $(OBJ)/libstrongswan/.libs:$(OBJ)/libcharon/.libs
+LIBFL = -lstrongswan -lcharon
 
 DEFS += -DPLUGINS=\""$(PLUGINS)\"" -DIPSEC_PIDDIR=\"${piddir}\"
 
diff --git a/src/charon-tkm/Makefile.in b/src/charon-tkm/Makefile.in
index bff198a..81afd4d 100644
--- a/src/charon-tkm/Makefile.in
+++ b/src/charon-tkm/Makefile.in
@@ -329,6 +329,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -347,16 +349,14 @@ OBJ = $(abs_top_builddir)/src
 AM_CPPFLAGS = \
 	-include $(abs_top_builddir)/config.h \
 	-I$(SRC)/libstrongswan \
-	-I$(SRC)/libhydra \
 	-I$(SRC)/libcharon
 
 LIBLD = \
 	-L$(OBJ)/libstrongswan/.libs \
-	-L$(OBJ)/libhydra/.libs \
 	-L$(OBJ)/libcharon/.libs
 
-LIBPT = $(OBJ)/libstrongswan/.libs:$(OBJ)/libhydra/.libs:$(OBJ)/libcharon/.libs
-LIBFL = -lstrongswan -lhydra -lcharon
+LIBPT = $(OBJ)/libstrongswan/.libs:$(OBJ)/libcharon/.libs
+LIBFL = -lstrongswan -lcharon
 BUILD_OPTS = \
 	-XOBJ_DIR=$(abs_builddir)/obj \
 	-cargs $(AM_CPPFLAGS) $(DEFS) \
diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c
index 3923c8a..13352e5 100644
--- a/src/charon-tkm/src/charon-tkm.c
+++ b/src/charon-tkm/src/charon-tkm.c
@@ -26,7 +26,6 @@
 #include <libgen.h>
 #include <errno.h>
 
-#include <hydra.h>
 #include <daemon.h>
 #include <library.h>
 #include <utils/backtrace.h>
@@ -256,14 +255,6 @@ int main(int argc, char *argv[])
 		exit(status);
 	}
 
-	if (!libhydra_init())
-	{
-		dbg_syslog(DBG_DMN, 1, "initialization failed - aborting %s", dmn_name);
-		libhydra_deinit();
-		library_deinit();
-		exit(status);
-	}
-
 	if (!libcharon_init())
 	{
 		dbg_syslog(DBG_DMN, 1, "initialization failed - aborting %s", dmn_name);
@@ -391,7 +382,6 @@ int main(int argc, char *argv[])
 deinit:
 	destroy_dh_mapping();
 	libcharon_deinit();
-	libhydra_deinit();
 	library_deinit();
 	tkm_deinit();
 	return status;
diff --git a/src/charon-tkm/src/ees/ees_callbacks.c b/src/charon-tkm/src/ees/ees_callbacks.c
index 74c0d36..f4107d9 100644
--- a/src/charon-tkm/src/ees/ees_callbacks.c
+++ b/src/charon-tkm/src/ees/ees_callbacks.c
@@ -14,7 +14,7 @@
  * for more details.
  */
 
-#include <hydra.h>
+#include <daemon.h>
 #include <utils/debug.h>
 #include <tkm/constants.h>
 #include <tkm/types.h>
@@ -25,8 +25,7 @@
 void charon_esa_acquire(result_type *res, const sp_id_type sp_id)
 {
 	DBG1(DBG_KNL, "ees: acquire received for reqid %u", sp_id);
-	hydra->kernel_interface->acquire(hydra->kernel_interface, sp_id, NULL,
-									 NULL);
+	charon->kernel->acquire(charon->kernel, sp_id, NULL, NULL);
 	*res = TKM_OK;
 }
 
@@ -47,6 +46,5 @@ void charon_esa_expire(result_type *res, const sp_id_type sp_id,
 
 	DBG1(DBG_KNL, "ees: expire received for reqid %u, spi %x, dst %H", sp_id,
 		 ntohl(spi_rem), dst);
-	hydra->kernel_interface->expire(hydra->kernel_interface, protocol,
-									spi_rem, dst, hard != 0);
+	charon->kernel->expire(charon->kernel, protocol, spi_rem, dst, hard != 0);
 }
diff --git a/src/charon-tkm/tests/keymat_tests.c b/src/charon-tkm/tests/keymat_tests.c
index d087bee..8bba1f9 100644
--- a/src/charon-tkm/tests/keymat_tests.c
+++ b/src/charon-tkm/tests/keymat_tests.c
@@ -17,7 +17,6 @@
 #include <tests/test_suite.h>
 
 #include <daemon.h>
-#include <hydra.h>
 #include <config/proposal.h>
 #include <encoding/payloads/ike_header.h>
 #include <tkm/client.h>
diff --git a/src/charon-tkm/tests/tests.c b/src/charon-tkm/tests/tests.c
index ac152b6..e3cd2d9 100644
--- a/src/charon-tkm/tests/tests.c
+++ b/src/charon-tkm/tests/tests.c
@@ -18,7 +18,6 @@
 #include <tests/test_runner.h>
 
 #include <library.h>
-#include <hydra.h>
 #include <daemon.h>
 
 #include "tkm.h"
@@ -50,7 +49,6 @@ static bool test_runner_init(bool init)
 
 	if (init)
 	{
-		libhydra_init();
 		libcharon_init();
 		lib->settings->set_int(lib->settings,
 							   "test-runner.filelog.stdout.default", 0);
@@ -74,8 +72,6 @@ static bool test_runner_init(bool init)
 
 		plugin_loader_add_plugindirs(BUILDDIR "/src/libstrongswan/plugins",
 									 PLUGINS);
-		plugin_loader_add_plugindirs(BUILDDIR "/src/libhydra/plugins",
-									 PLUGINS);
 		plugin_loader_add_plugindirs(BUILDDIR "/src/libcharon/plugins",
 									 PLUGINS);
 		if (charon->initialize(charon, PLUGINS))
@@ -95,7 +91,6 @@ static bool test_runner_init(bool init)
 
 	destroy_dh_mapping();
 	libcharon_deinit();
-	libhydra_deinit();
 	return result;
 }
 
diff --git a/src/charon/Android.mk b/src/charon/Android.mk
index 852d73c..92a0270 100644
--- a/src/charon/Android.mk
+++ b/src/charon/Android.mk
@@ -8,7 +8,6 @@ charon.c
 # build charon -----------------------------------------------------------------
 
 LOCAL_C_INCLUDES += \
-	$(strongswan_PATH)/src/libhydra \
 	$(strongswan_PATH)/src/libcharon \
 	$(strongswan_PATH)/src/libstrongswan
 
@@ -23,7 +22,7 @@ LOCAL_ARM_MODE := arm
 
 LOCAL_PRELINK_MODULE := false
 
-LOCAL_SHARED_LIBRARIES += libstrongswan libhydra libcharon
+LOCAL_SHARED_LIBRARIES += libstrongswan libcharon
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am
index 6c5b88e..c6a6f40 100644
--- a/src/charon/Makefile.am
+++ b/src/charon/Makefile.am
@@ -7,7 +7,6 @@ charon.o :	$(top_builddir)/config.status
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_DIR=\"${ipsecdir}\" \
 	-DIPSEC_PIDDIR=\"${piddir}\" \
@@ -15,7 +14,6 @@ AM_CPPFLAGS = \
 
 charon_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
 	-lm $(PTHREADLIB) $(DLLIB)
 
diff --git a/src/charon/Makefile.in b/src/charon/Makefile.in
index e1cc5c2..b4abeff 100644
--- a/src/charon/Makefile.in
+++ b/src/charon/Makefile.in
@@ -106,7 +106,6 @@ charon_OBJECTS = $(am_charon_OBJECTS)
 am__DEPENDENCIES_1 =
 charon_DEPENDENCIES =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 AM_V_lt = $(am__v_lt_ at AM_V@)
@@ -386,6 +385,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -404,7 +405,6 @@ charon.c
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_DIR=\"${ipsecdir}\" \
 	-DIPSEC_PIDDIR=\"${piddir}\" \
@@ -412,7 +412,6 @@ AM_CPPFLAGS = \
 
 charon_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
 	-lm $(PTHREADLIB) $(DLLIB)
 
diff --git a/src/charon/charon.c b/src/charon/charon.c
index 4c2a9a4..116ce7e 100644
--- a/src/charon/charon.c
+++ b/src/charon/charon.c
@@ -27,7 +27,6 @@
 #include <fcntl.h>
 #include <errno.h>
 
-#include <hydra.h>
 #include <daemon.h>
 
 #include <library.h>
@@ -309,14 +308,6 @@ int main(int argc, char *argv[])
 		exit(SS_RC_DAEMON_INTEGRITY);
 	}
 
-	if (!libhydra_init())
-	{
-		dbg_stderr(DBG_DMN, 1, "initialization failed - aborting charon");
-		libhydra_deinit();
-		library_deinit();
-		exit(SS_RC_INITIALIZATION_FAILED);
-	}
-
 	if (!libcharon_init())
 	{
 		dbg_stderr(DBG_DMN, 1, "initialization failed - aborting charon");
@@ -403,7 +394,6 @@ int main(int argc, char *argv[])
 	{
 		DBG1(DBG_DMN, "integrity tests enabled:");
 		DBG1(DBG_DMN, "lib    'libstrongswan': passed file and segment integrity tests");
-		DBG1(DBG_DMN, "lib    'libhydra': passed file and segment integrity tests");
 		DBG1(DBG_DMN, "lib    'libcharon': passed file and segment integrity tests");
 		DBG1(DBG_DMN, "daemon 'charon': passed file integrity test");
 	}
@@ -457,7 +447,6 @@ int main(int argc, char *argv[])
 
 deinit:
 	libcharon_deinit();
-	libhydra_deinit();
 	library_deinit();
 	return status;
 }
diff --git a/src/checksum/Makefile.am b/src/checksum/Makefile.am
index b358699..9cc5fb6 100644
--- a/src/checksum/Makefile.am
+++ b/src/checksum/Makefile.am
@@ -8,7 +8,6 @@ EXTRA_PROGRAMS = checksum_builder
 checksum_builder_SOURCES = checksum_builder.c
 checksum_builder_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
 	$(DLLIB)
 checksum_builder_LDFLAGS = -rpath '$(DESTDIR)$(ipseclibdir)'
@@ -17,7 +16,6 @@ CLEANFILES = checksum.c $(EXTRA_PROGRAMS)
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DPLUGINDIR=\"${DESTDIR}${plugindir}\"
 
@@ -35,14 +33,6 @@ if !MONOLITHIC
   AM_CPPFLAGS += -DS_PLUGINS=\""${s_plugins}\""
 endif
 
-if USE_LIBHYDRA
-  deps += $(top_builddir)/src/libhydra/libhydra.la
-  libs += $(DESTDIR)$(ipseclibdir)/libhydra.so
-if !MONOLITHIC
-  AM_CPPFLAGS += -DH_PLUGINS=\""${h_plugins}\""
-endif
-endif
-
 if USE_LIBIPSEC
   deps += $(top_builddir)/src/libipsec/libipsec.la
   libs += $(DESTDIR)$(ipseclibdir)/libipsec.so
diff --git a/src/checksum/Makefile.in b/src/checksum/Makefile.in
index 4e41346..2584beb 100644
--- a/src/checksum/Makefile.in
+++ b/src/checksum/Makefile.in
@@ -80,34 +80,31 @@ build_triplet = @build@
 host_triplet = @host@
 EXTRA_PROGRAMS = checksum_builder$(EXEEXT)
 @MONOLITHIC_FALSE at am__append_1 = -DS_PLUGINS=\""${s_plugins}\""
- at USE_LIBHYDRA_TRUE@am__append_2 = $(top_builddir)/src/libhydra/libhydra.la
- at USE_LIBHYDRA_TRUE@am__append_3 = $(DESTDIR)$(ipseclibdir)/libhydra.so
- at MONOLITHIC_FALSE@@USE_LIBHYDRA_TRUE at am__append_4 = -DH_PLUGINS=\""${h_plugins}\""
- at USE_LIBIPSEC_TRUE@am__append_5 = $(top_builddir)/src/libipsec/libipsec.la
- at USE_LIBIPSEC_TRUE@am__append_6 = $(DESTDIR)$(ipseclibdir)/libipsec.so
- at USE_TLS_TRUE@am__append_7 = $(top_builddir)/src/libtls/libtls.la
- at USE_TLS_TRUE@am__append_8 = $(DESTDIR)$(ipseclibdir)/libtls.so
- at USE_RADIUS_TRUE@am__append_9 = $(top_builddir)/src/libradius/libradius.la
- at USE_RADIUS_TRUE@am__append_10 = $(DESTDIR)$(ipseclibdir)/libradius.so
- at USE_LIBPTTLS_TRUE@am__append_11 = $(top_builddir)/src/libpttls/libpttls.la
- at USE_LIBPTTLS_TRUE@am__append_12 = $(DESTDIR)$(ipseclibdir)/libpttls.so
- at USE_LIBTNCCS_TRUE@am__append_13 = $(top_builddir)/src/libtnccs/libtnccs.la
- at USE_LIBTNCCS_TRUE@am__append_14 = $(DESTDIR)$(ipseclibdir)/libtnccs.so
- at MONOLITHIC_FALSE@@USE_LIBTNCCS_TRUE at am__append_15 = -DT_PLUGINS=\""${t_plugins}\""
- at USE_SIMAKA_TRUE@am__append_16 = $(top_builddir)/src/libsimaka/libsimaka.la
- at USE_SIMAKA_TRUE@am__append_17 = $(DESTDIR)$(ipseclibdir)/libsimaka.so
- at USE_IMCV_TRUE@am__append_18 = $(top_builddir)/src/libimcv/libimcv.la
- at USE_IMCV_TRUE@am__append_19 = $(DESTDIR)$(ipseclibdir)/libimcv.so
- at USE_CHARON_TRUE@am__append_20 = $(top_builddir)/src/libcharon/libcharon.la
- at USE_CHARON_TRUE@am__append_21 = $(DESTDIR)$(ipseclibdir)/libcharon.so
- at USE_CHARON_TRUE@am__append_22 = $(DESTDIR)$(ipsecdir)/charon
- at MONOLITHIC_FALSE@@USE_CHARON_TRUE at am__append_23 = -DC_PLUGINS=\""${c_plugins}\""
- at USE_CMD_TRUE@am__append_24 = $(DESTDIR)$(sbindir)/charon-cmd
- at USE_SCEPCLIENT_TRUE@am__append_25 = $(DESTDIR)$(ipsecdir)/scepclient
- at USE_PKI_TRUE@am__append_26 = $(DESTDIR)$(bindir)/pki
- at USE_SWANCTL_TRUE@am__append_27 = $(DESTDIR)$(sbindir)/swanctl
- at USE_ATTR_SQL_TRUE@am__append_28 = $(DESTDIR)$(ipsecdir)/pool
- at USE_IMV_ATTESTATION_TRUE@am__append_29 = $(DESTDIR)$(ipsecdir)/attest
+ at USE_LIBIPSEC_TRUE@am__append_2 = $(top_builddir)/src/libipsec/libipsec.la
+ at USE_LIBIPSEC_TRUE@am__append_3 = $(DESTDIR)$(ipseclibdir)/libipsec.so
+ at USE_TLS_TRUE@am__append_4 = $(top_builddir)/src/libtls/libtls.la
+ at USE_TLS_TRUE@am__append_5 = $(DESTDIR)$(ipseclibdir)/libtls.so
+ at USE_RADIUS_TRUE@am__append_6 = $(top_builddir)/src/libradius/libradius.la
+ at USE_RADIUS_TRUE@am__append_7 = $(DESTDIR)$(ipseclibdir)/libradius.so
+ at USE_LIBPTTLS_TRUE@am__append_8 = $(top_builddir)/src/libpttls/libpttls.la
+ at USE_LIBPTTLS_TRUE@am__append_9 = $(DESTDIR)$(ipseclibdir)/libpttls.so
+ at USE_LIBTNCCS_TRUE@am__append_10 = $(top_builddir)/src/libtnccs/libtnccs.la
+ at USE_LIBTNCCS_TRUE@am__append_11 = $(DESTDIR)$(ipseclibdir)/libtnccs.so
+ at MONOLITHIC_FALSE@@USE_LIBTNCCS_TRUE at am__append_12 = -DT_PLUGINS=\""${t_plugins}\""
+ at USE_SIMAKA_TRUE@am__append_13 = $(top_builddir)/src/libsimaka/libsimaka.la
+ at USE_SIMAKA_TRUE@am__append_14 = $(DESTDIR)$(ipseclibdir)/libsimaka.so
+ at USE_IMCV_TRUE@am__append_15 = $(top_builddir)/src/libimcv/libimcv.la
+ at USE_IMCV_TRUE@am__append_16 = $(DESTDIR)$(ipseclibdir)/libimcv.so
+ at USE_CHARON_TRUE@am__append_17 = $(top_builddir)/src/libcharon/libcharon.la
+ at USE_CHARON_TRUE@am__append_18 = $(DESTDIR)$(ipseclibdir)/libcharon.so
+ at USE_CHARON_TRUE@am__append_19 = $(DESTDIR)$(ipsecdir)/charon
+ at MONOLITHIC_FALSE@@USE_CHARON_TRUE at am__append_20 = -DC_PLUGINS=\""${c_plugins}\""
+ at USE_CMD_TRUE@am__append_21 = $(DESTDIR)$(sbindir)/charon-cmd
+ at USE_SCEPCLIENT_TRUE@am__append_22 = $(DESTDIR)$(ipsecdir)/scepclient
+ at USE_PKI_TRUE@am__append_23 = $(DESTDIR)$(bindir)/pki
+ at USE_SWANCTL_TRUE@am__append_24 = $(DESTDIR)$(sbindir)/swanctl
+ at USE_ATTR_SQL_TRUE@am__append_25 = $(DESTDIR)$(ipsecdir)/pool
+ at USE_IMV_ATTESTATION_TRUE@am__append_26 = $(DESTDIR)$(ipsecdir)/attest
 subdir = src/checksum
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/depcomp
@@ -173,7 +170,6 @@ checksum_builder_OBJECTS = $(am_checksum_builder_OBJECTS)
 am__DEPENDENCIES_1 =
 checksum_builder_DEPENDENCIES =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
 	$(am__DEPENDENCIES_1)
 checksum_builder_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
@@ -453,6 +449,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -475,16 +473,15 @@ libchecksum_la_LDFLAGS = -module -avoid-version -rpath '$(ipseclibdir)'
 checksum_builder_SOURCES = checksum_builder.c
 checksum_builder_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
 	$(DLLIB)
 
 checksum_builder_LDFLAGS = -rpath '$(DESTDIR)$(ipseclibdir)'
 CLEANFILES = checksum.c $(EXTRA_PROGRAMS)
 AM_CPPFLAGS = -I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon \
+	-I$(top_srcdir)/src/libcharon \
 	-DPLUGINDIR=\"${DESTDIR}${plugindir}\" $(am__append_1) \
-	$(am__append_4) $(am__append_15) $(am__append_23)
+	$(am__append_12) $(am__append_20)
 AM_CFLAGS = \
 	$(PLUGIN_CFLAGS)
 
@@ -493,16 +490,16 @@ AM_CFLAGS = \
 # to the installed libraries. for executables we use the built files directly
 # as these are not relinked during installation.
 deps = $(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(am__append_2) $(am__append_5) $(am__append_7) \
-	$(am__append_9) $(am__append_11) $(am__append_13) \
-	$(am__append_16) $(am__append_18) $(am__append_20)
+	$(am__append_2) $(am__append_4) $(am__append_6) \
+	$(am__append_8) $(am__append_10) $(am__append_13) \
+	$(am__append_15) $(am__append_17)
 libs = $(DESTDIR)$(ipseclibdir)/libstrongswan.so $(am__append_3) \
-	$(am__append_6) $(am__append_8) $(am__append_10) \
-	$(am__append_12) $(am__append_14) $(am__append_17) \
-	$(am__append_19) $(am__append_21)
-exes = $(am__append_22) $(am__append_24) $(am__append_25) \
-	$(am__append_26) $(am__append_27) $(am__append_28) \
-	$(am__append_29)
+	$(am__append_5) $(am__append_7) $(am__append_9) \
+	$(am__append_11) $(am__append_14) $(am__append_16) \
+	$(am__append_18)
+exes = $(am__append_19) $(am__append_21) $(am__append_22) \
+	$(am__append_23) $(am__append_24) $(am__append_25) \
+	$(am__append_26)
 all: all-am
 
 .SUFFIXES:
diff --git a/src/checksum/checksum_builder.c b/src/checksum/checksum_builder.c
index cc8185e..65399f5 100644
--- a/src/checksum/checksum_builder.c
+++ b/src/checksum/checksum_builder.c
@@ -19,7 +19,6 @@
 #include <dlfcn.h>
 
 #include <library.h>
-#include <hydra.h>
 #include <daemon.h>
 #include <collections/enumerator.h>
 
@@ -128,9 +127,8 @@ int main(int argc, char* argv[])
 {
 	int i;
 
-	/* forces link against libhydra/libcharon, imports symbols needed to
+	/* forces link against libcharon, imports symbols needed to
 	 * dlopen plugins */
-	hydra = NULL;
 	charon = NULL;
 
 	/* avoid confusing leak reports in build process */
@@ -159,9 +157,6 @@ int main(int argc, char* argv[])
 #ifdef S_PLUGINS
 	build_plugin_checksums(S_PLUGINS);
 #endif
-#ifdef H_PLUGINS
-	build_plugin_checksums(H_PLUGINS);
-#endif
 #ifdef T_PLUGINS
 	build_plugin_checksums(T_PLUGINS);
 #endif
diff --git a/src/conftest/Makefile.am b/src/conftest/Makefile.am
index eeb26f2..2d4e439 100644
--- a/src/conftest/Makefile.am
+++ b/src/conftest/Makefile.am
@@ -2,7 +2,6 @@ ipsec_PROGRAMS = conftest
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DPLUGINS=\""${charon_plugins}\""
 
@@ -20,7 +19,6 @@ conftest_SOURCES = conftest.c conftest.h config.c config.h actions.c actions.h \
 
 conftest_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
 	-lm $(PTHREADLIB) $(DLLIB)
 
diff --git a/src/conftest/Makefile.in b/src/conftest/Makefile.in
index 78438d8..f5647f9 100644
--- a/src/conftest/Makefile.in
+++ b/src/conftest/Makefile.in
@@ -120,7 +120,6 @@ conftest_OBJECTS = $(am_conftest_OBJECTS)
 am__DEPENDENCIES_1 =
 conftest_DEPENDENCIES =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 AM_V_lt = $(am__v_lt_ at AM_V@)
@@ -400,6 +399,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -415,7 +416,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DPLUGINS=\""${charon_plugins}\""
 
@@ -432,7 +432,6 @@ conftest_SOURCES = conftest.c conftest.h config.c config.h actions.c actions.h \
 
 conftest_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la \
 	-lm $(PTHREADLIB) $(DLLIB)
 
diff --git a/src/conftest/conftest.c b/src/conftest/conftest.c
index edfe0ca..d10f3c7 100644
--- a/src/conftest/conftest.c
+++ b/src/conftest/conftest.c
@@ -356,7 +356,6 @@ static void cleanup()
 	free(conftest->suite_dir);
 	free(conftest);
 	libcharon_deinit();
-	libhydra_deinit();
 	library_deinit();
 }
 
@@ -442,16 +441,9 @@ int main(int argc, char *argv[])
 		library_deinit();
 		return SS_RC_LIBSTRONGSWAN_INTEGRITY;
 	}
-	if (!libhydra_init())
-	{
-		libhydra_deinit();
-		library_deinit();
-		return SS_RC_INITIALIZATION_FAILED;
-	}
 	if (!libcharon_init())
 	{
 		libcharon_deinit();
-		libhydra_deinit();
 		library_deinit();
 		return SS_RC_INITIALIZATION_FAILED;
 	}
diff --git a/src/conftest/conftest.h b/src/conftest/conftest.h
index 6bbdabd..2d03204 100644
--- a/src/conftest/conftest.h
+++ b/src/conftest/conftest.h
@@ -21,7 +21,6 @@
 #define CONFTEST_H_
 
 #include <library.h>
-#include <hydra.h>
 #include <daemon.h>
 #include <credentials/sets/mem_cred.h>
 
diff --git a/src/dumm/Makefile.in b/src/dumm/Makefile.in
index 2ecf611..6525fbc 100644
--- a/src/dumm/Makefile.in
+++ b/src/dumm/Makefile.in
@@ -421,6 +421,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/include/Makefile.in b/src/include/Makefile.in
index 5740544..9f4becb 100644
--- a/src/include/Makefile.in
+++ b/src/include/Makefile.in
@@ -329,6 +329,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/ipsec/Makefile.in b/src/ipsec/Makefile.in
index d4dafcb..72022ed 100644
--- a/src/ipsec/Makefile.in
+++ b/src/ipsec/Makefile.in
@@ -363,6 +363,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/ipsec/_ipsec.8 b/src/ipsec/_ipsec.8
index fa46e79..686c1ce 100644
--- a/src/ipsec/_ipsec.8
+++ b/src/ipsec/_ipsec.8
@@ -1,4 +1,4 @@
-.TH IPSEC 8 "2013-10-29" "5.4.0dr1" "strongSwan"
+.TH IPSEC 8 "2013-10-29" "5.4.0rc1" "strongSwan"
 .
 .SH NAME
 .
diff --git a/src/ipsec/_ipsec.in b/src/ipsec/_ipsec.in
index 89c7ef7..a002614 100644
--- a/src/ipsec/_ipsec.in
+++ b/src/ipsec/_ipsec.in
@@ -259,10 +259,15 @@ stop)
 			loop=110
 			while [ $loop -gt 0 ] ; do
 				kill -0 $spid 2>/dev/null || break
-				sleep 0.1
+				sleep 0.1 2>/dev/null
+				if [ $? -ne 0 ]
+				then
+					sleep 1
+					loop=$(($loop - 9))
+				fi
 				loop=$(($loop - 1))
 			done
-			if [ $loop -eq 0 ]
+			if [ $loop -le 0 ]
 			then
 				kill -KILL $spid 2>/dev/null
 				rm -f $IPSEC_STARTER_PID
diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk
index 1008579..55e6bc5 100644
--- a/src/libcharon/Android.mk
+++ b/src/libcharon/Android.mk
@@ -47,7 +47,10 @@ encoding/payloads/unknown_payload.c encoding/payloads/unknown_payload.h \
 encoding/payloads/vendor_id_payload.c encoding/payloads/vendor_id_payload.h \
 encoding/payloads/hash_payload.c encoding/payloads/hash_payload.h \
 encoding/payloads/fragment_payload.c encoding/payloads/fragment_payload.h \
-kernel/kernel_handler.c kernel/kernel_handler.h \
+kernel/kernel_interface.c kernel/kernel_interface.h \
+kernel/kernel_ipsec.c kernel/kernel_ipsec.h \
+kernel/kernel_net.c kernel/kernel_net.h \
+kernel/kernel_listener.h kernel/kernel_handler.c kernel/kernel_handler.h \
 network/receiver.c network/receiver.h network/sender.c network/sender.h \
 network/socket.c network/socket.h \
 network/socket_manager.c network/socket_manager.h \
@@ -56,6 +59,7 @@ 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/redirect_job.c processing/jobs/redirect_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 \
 processing/jobs/retransmit_job.c processing/jobs/retransmit_job.h \
@@ -81,6 +85,7 @@ sa/child_sa_manager.c sa/child_sa_manager.h \
 sa/task_manager.h sa/task_manager.c \
 sa/shunt_manager.c sa/shunt_manager.h \
 sa/trap_manager.c sa/trap_manager.h \
+sa/redirect_provider.h sa/redirect_manager.c sa/redirect_manager.h \
 sa/task.c sa/task.h
 
 libcharon_la_SOURCES += \
@@ -104,8 +109,10 @@ sa/ikev2/tasks/ike_mobike.c sa/ikev2/tasks/ike_mobike.h \
 sa/ikev2/tasks/ike_rekey.c sa/ikev2/tasks/ike_rekey.h \
 sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \
 sa/ikev2/tasks/ike_reauth_complete.c sa/ikev2/tasks/ike_reauth_complete.h \
+sa/ikev2/tasks/ike_redirect.c sa/ikev2/tasks/ike_redirect.h \
 sa/ikev2/tasks/ike_auth_lifetime.c sa/ikev2/tasks/ike_auth_lifetime.h \
-sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h
+sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h \
+sa/ikev2/tasks/ike_verify_peer_cert.c sa/ikev2/tasks/ike_verify_peer_cert.h
 
 libcharon_la_SOURCES += \
 sa/ikev1/keymat_v1.c sa/ikev1/keymat_v1.h \
@@ -149,6 +156,8 @@ endif
 
 LOCAL_SRC_FILES += $(call add_plugin, attr)
 
+LOCAL_SRC_FILES += $(call add_plugin, p-cscf)
+
 LOCAL_SRC_FILES += $(call add_plugin, eap-aka)
 
 LOCAL_SRC_FILES += $(call add_plugin, eap-aka-3gpp2)
@@ -216,6 +225,10 @@ endif
 
 LOCAL_SRC_FILES += $(call add_plugin, load-tester)
 
+LOCAL_SRC_FILES += $(call add_plugin, kernel-pfkey)
+
+LOCAL_SRC_FILES += $(call add_plugin, kernel-netlink)
+
 LOCAL_SRC_FILES += $(call add_plugin, socket-default)
 
 LOCAL_SRC_FILES += $(call add_plugin, socket-dynamic)
@@ -228,7 +241,6 @@ endif
 # build libcharon --------------------------------------------------------------
 
 LOCAL_C_INCLUDES += \
-	$(strongswan_PATH)/src/libhydra \
 	$(strongswan_PATH)/src/libstrongswan
 
 LOCAL_CFLAGS := $(strongswan_CFLAGS)
@@ -241,6 +253,6 @@ LOCAL_ARM_MODE := arm
 
 LOCAL_PRELINK_MODULE := false
 
-LOCAL_SHARED_LIBRARIES += libstrongswan libhydra
+LOCAL_SHARED_LIBRARIES += libstrongswan
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am
index cd81a5e..9f07078 100644
--- a/src/libcharon/Makefile.am
+++ b/src/libcharon/Makefile.am
@@ -8,6 +8,7 @@ attributes/mem_pool.c attributes/mem_pool.h \
 bus/bus.c bus/bus.h \
 bus/listeners/listener.h \
 bus/listeners/logger.h \
+bus/listeners/custom_logger.h \
 bus/listeners/file_logger.c bus/listeners/file_logger.h \
 config/backend_manager.c config/backend_manager.h config/backend.h \
 config/child_cfg.c config/child_cfg.h \
@@ -45,7 +46,10 @@ encoding/payloads/unknown_payload.c encoding/payloads/unknown_payload.h \
 encoding/payloads/vendor_id_payload.c encoding/payloads/vendor_id_payload.h \
 encoding/payloads/hash_payload.c encoding/payloads/hash_payload.h \
 encoding/payloads/fragment_payload.c encoding/payloads/fragment_payload.h \
-kernel/kernel_handler.c kernel/kernel_handler.h \
+kernel/kernel_interface.c kernel/kernel_interface.h \
+kernel/kernel_ipsec.c kernel/kernel_ipsec.h \
+kernel/kernel_net.c kernel/kernel_net.h \
+kernel/kernel_listener.h kernel/kernel_handler.c kernel/kernel_handler.h \
 network/receiver.c network/receiver.h network/sender.c network/sender.h \
 network/socket.c network/socket.h \
 network/socket_manager.c network/socket_manager.h \
@@ -54,6 +58,7 @@ 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/redirect_job.c processing/jobs/redirect_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 \
 processing/jobs/retransmit_job.c processing/jobs/retransmit_job.h \
@@ -79,6 +84,7 @@ sa/child_sa_manager.c sa/child_sa_manager.h \
 sa/task_manager.h sa/task_manager.c \
 sa/shunt_manager.c sa/shunt_manager.h \
 sa/trap_manager.c sa/trap_manager.h \
+sa/redirect_provider.h sa/redirect_manager.c sa/redirect_manager.h \
 sa/task.c sa/task.h
 
 if USE_IKEV2
@@ -103,8 +109,10 @@ sa/ikev2/tasks/ike_mobike.c sa/ikev2/tasks/ike_mobike.h \
 sa/ikev2/tasks/ike_rekey.c sa/ikev2/tasks/ike_rekey.h \
 sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \
 sa/ikev2/tasks/ike_reauth_complete.c sa/ikev2/tasks/ike_reauth_complete.h \
+sa/ikev2/tasks/ike_redirect.c sa/ikev2/tasks/ike_redirect.h \
 sa/ikev2/tasks/ike_auth_lifetime.c sa/ikev2/tasks/ike_auth_lifetime.h \
-sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h
+sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h \
+sa/ikev2/tasks/ike_verify_peer_cert.c sa/ikev2/tasks/ike_verify_peer_cert.h
 endif
 
 if USE_IKEV1
@@ -142,7 +150,6 @@ daemon.lo :		$(top_builddir)/config.status
 AM_CPPFLAGS = \
 	-I${linux_headers} \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_DIR=\"${ipsecdir}\" \
 	-DIPSEC_PIDDIR=\"${piddir}\"
@@ -152,7 +159,6 @@ AM_LDFLAGS = \
 
 libcharon_la_LIBADD = \
   $(top_builddir)/src/libstrongswan/libstrongswan.la \
-  $(top_builddir)/src/libhydra/libhydra.la \
   -lm $(PTHREADLIB) $(DLLIB) $(SOCKLIB)
 
 if USE_WINDOWS
@@ -483,6 +489,13 @@ if MONOLITHIC
 endif
 endif
 
+if USE_P_CSCF
+  SUBDIRS += plugins/p_cscf
+if MONOLITHIC
+  libcharon_la_LIBADD += plugins/p_cscf/libstrongswan-p-cscf.la
+endif
+endif
+
 if USE_ANDROID_DNS
   SUBDIRS += plugins/android_dns
 if MONOLITHIC
@@ -511,6 +524,27 @@ if MONOLITHIC
 endif
 endif
 
+if USE_KERNEL_PFKEY
+  SUBDIRS += plugins/kernel_pfkey
+if MONOLITHIC
+  libcharon_la_LIBADD += plugins/kernel_pfkey/libstrongswan-kernel-pfkey.la
+endif
+endif
+
+if USE_KERNEL_PFROUTE
+  SUBDIRS += plugins/kernel_pfroute
+if MONOLITHIC
+  libcharon_la_LIBADD += plugins/kernel_pfroute/libstrongswan-kernel-pfroute.la
+endif
+endif
+
+if USE_KERNEL_NETLINK
+  SUBDIRS += plugins/kernel_netlink
+if MONOLITHIC
+  libcharon_la_LIBADD += plugins/kernel_netlink/libstrongswan-kernel-netlink.la
+endif
+endif
+
 if USE_KERNEL_LIBIPSEC
   SUBDIRS += plugins/kernel_libipsec
 if MONOLITHIC
diff --git a/src/libcharon/Makefile.in b/src/libcharon/Makefile.in
index 3d425e0..2ccae21 100644
--- a/src/libcharon/Makefile.in
+++ b/src/libcharon/Makefile.in
@@ -99,8 +99,10 @@ host_triplet = @host@
 @USE_IKEV2_TRUE at sa/ikev2/tasks/ike_rekey.c sa/ikev2/tasks/ike_rekey.h \
 @USE_IKEV2_TRUE at sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \
 @USE_IKEV2_TRUE at sa/ikev2/tasks/ike_reauth_complete.c sa/ikev2/tasks/ike_reauth_complete.h \
+ at USE_IKEV2_TRUE@sa/ikev2/tasks/ike_redirect.c sa/ikev2/tasks/ike_redirect.h \
 @USE_IKEV2_TRUE at sa/ikev2/tasks/ike_auth_lifetime.c sa/ikev2/tasks/ike_auth_lifetime.h \
- at USE_IKEV2_TRUE@sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h
+ at USE_IKEV2_TRUE@sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h \
+ at USE_IKEV2_TRUE@sa/ikev2/tasks/ike_verify_peer_cert.c sa/ikev2/tasks/ike_verify_peer_cert.h
 
 @USE_IKEV1_TRUE at am__append_2 = \
 @USE_IKEV1_TRUE at sa/ikev1/keymat_v1.c sa/ikev1/keymat_v1.h \
@@ -221,58 +223,66 @@ host_triplet = @host@
 @MONOLITHIC_TRUE@@USE_DHCP_TRUE at am__append_85 = plugins/dhcp/libstrongswan-dhcp.la
 @USE_OSX_ATTR_TRUE at am__append_86 = plugins/osx_attr
 @MONOLITHIC_TRUE@@USE_OSX_ATTR_TRUE at am__append_87 = plugins/osx_attr/libstrongswan-osx-attr.la
- at USE_ANDROID_DNS_TRUE@am__append_88 = plugins/android_dns
- at MONOLITHIC_TRUE@@USE_ANDROID_DNS_TRUE at am__append_89 = plugins/android_dns/libstrongswan-android-dns.la
- at USE_ANDROID_LOG_TRUE@am__append_90 = plugins/android_log
- at MONOLITHIC_TRUE@@USE_ANDROID_LOG_TRUE at am__append_91 = plugins/android_log/libstrongswan-android-log.la
- at USE_MAEMO_TRUE@am__append_92 = plugins/maemo
- at MONOLITHIC_TRUE@@USE_MAEMO_TRUE at am__append_93 = plugins/maemo/libstrongswan-maemo.la
- at USE_HA_TRUE@am__append_94 = plugins/ha
- at MONOLITHIC_TRUE@@USE_HA_TRUE at am__append_95 = plugins/ha/libstrongswan-ha.la
- at USE_KERNEL_LIBIPSEC_TRUE@am__append_96 = plugins/kernel_libipsec
- at MONOLITHIC_TRUE@@USE_KERNEL_LIBIPSEC_TRUE at am__append_97 = plugins/kernel_libipsec/libstrongswan-kernel-libipsec.la
- at USE_KERNEL_WFP_TRUE@am__append_98 = plugins/kernel_wfp
- at MONOLITHIC_TRUE@@USE_KERNEL_WFP_TRUE at am__append_99 = plugins/kernel_wfp/libstrongswan-kernel-wfp.la
- at USE_KERNEL_IPH_TRUE@am__append_100 = plugins/kernel_iph
- at MONOLITHIC_TRUE@@USE_KERNEL_IPH_TRUE at am__append_101 = plugins/kernel_iph/libstrongswan-kernel-iph.la
- at USE_WHITELIST_TRUE@am__append_102 = plugins/whitelist
- at MONOLITHIC_TRUE@@USE_WHITELIST_TRUE at am__append_103 = plugins/whitelist/libstrongswan-whitelist.la
- at USE_LOOKIP_TRUE@am__append_104 = plugins/lookip
- at MONOLITHIC_TRUE@@USE_LOOKIP_TRUE at am__append_105 = plugins/lookip/libstrongswan-lookip.la
- at USE_ERROR_NOTIFY_TRUE@am__append_106 = plugins/error_notify
- at MONOLITHIC_TRUE@@USE_ERROR_NOTIFY_TRUE at am__append_107 = plugins/error_notify/libstrongswan-error-notify.la
- at USE_CERTEXPIRE_TRUE@am__append_108 = plugins/certexpire
- at MONOLITHIC_TRUE@@USE_CERTEXPIRE_TRUE at am__append_109 = plugins/certexpire/libstrongswan-certexpire.la
- at USE_SYSTIME_FIX_TRUE@am__append_110 = plugins/systime_fix
- at MONOLITHIC_TRUE@@USE_SYSTIME_FIX_TRUE at am__append_111 = plugins/systime_fix/libstrongswan-systime-fix.la
- at USE_LED_TRUE@am__append_112 = plugins/led
- at MONOLITHIC_TRUE@@USE_LED_TRUE at am__append_113 = plugins/led/libstrongswan-led.la
- at USE_DUPLICHECK_TRUE@am__append_114 = plugins/duplicheck
- at MONOLITHIC_TRUE@@USE_DUPLICHECK_TRUE at am__append_115 = plugins/duplicheck/libstrongswan-duplicheck.la
- at USE_COUPLING_TRUE@am__append_116 = plugins/coupling
- at MONOLITHIC_TRUE@@USE_COUPLING_TRUE at am__append_117 = plugins/coupling/libstrongswan-coupling.la
- at USE_RADATTR_TRUE@am__append_118 = plugins/radattr
- at MONOLITHIC_TRUE@@USE_RADATTR_TRUE at am__append_119 = plugins/radattr/libstrongswan-radattr.la
- at USE_UCI_TRUE@am__append_120 = plugins/uci
- at MONOLITHIC_TRUE@@USE_UCI_TRUE at am__append_121 = plugins/uci/libstrongswan-uci.la
- at USE_ADDRBLOCK_TRUE@am__append_122 = plugins/addrblock
- at MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE at am__append_123 = plugins/addrblock/libstrongswan-addrblock.la
- at USE_UNITY_TRUE@am__append_124 = plugins/unity
- at MONOLITHIC_TRUE@@USE_UNITY_TRUE at am__append_125 = plugins/unity/libstrongswan-unity.la
- at USE_XAUTH_GENERIC_TRUE@am__append_126 = plugins/xauth_generic
- at MONOLITHIC_TRUE@@USE_XAUTH_GENERIC_TRUE at am__append_127 = plugins/xauth_generic/libstrongswan-xauth-generic.la
- at USE_XAUTH_EAP_TRUE@am__append_128 = plugins/xauth_eap
- at MONOLITHIC_TRUE@@USE_XAUTH_EAP_TRUE at am__append_129 = plugins/xauth_eap/libstrongswan-xauth-eap.la
- at USE_XAUTH_PAM_TRUE@am__append_130 = plugins/xauth_pam
- at MONOLITHIC_TRUE@@USE_XAUTH_PAM_TRUE at am__append_131 = plugins/xauth_pam/libstrongswan-xauth-pam.la
- at USE_XAUTH_NOAUTH_TRUE@am__append_132 = plugins/xauth_noauth
- at MONOLITHIC_TRUE@@USE_XAUTH_NOAUTH_TRUE at am__append_133 = plugins/xauth_noauth/libstrongswan-xauth-noauth.la
- at USE_RESOLVE_TRUE@am__append_134 = plugins/resolve
- at MONOLITHIC_TRUE@@USE_RESOLVE_TRUE at am__append_135 = plugins/resolve/libstrongswan-resolve.la
- at USE_ATTR_TRUE@am__append_136 = plugins/attr
- at MONOLITHIC_TRUE@@USE_ATTR_TRUE at am__append_137 = plugins/attr/libstrongswan-attr.la
- at USE_ATTR_SQL_TRUE@am__append_138 = plugins/attr_sql
- at MONOLITHIC_TRUE@@USE_ATTR_SQL_TRUE at am__append_139 = plugins/attr_sql/libstrongswan-attr-sql.la
+ at USE_P_CSCF_TRUE@am__append_88 = plugins/p_cscf
+ at MONOLITHIC_TRUE@@USE_P_CSCF_TRUE at am__append_89 = plugins/p_cscf/libstrongswan-p-cscf.la
+ at USE_ANDROID_DNS_TRUE@am__append_90 = plugins/android_dns
+ at MONOLITHIC_TRUE@@USE_ANDROID_DNS_TRUE at am__append_91 = plugins/android_dns/libstrongswan-android-dns.la
+ at USE_ANDROID_LOG_TRUE@am__append_92 = plugins/android_log
+ at MONOLITHIC_TRUE@@USE_ANDROID_LOG_TRUE at am__append_93 = plugins/android_log/libstrongswan-android-log.la
+ at USE_MAEMO_TRUE@am__append_94 = plugins/maemo
+ at MONOLITHIC_TRUE@@USE_MAEMO_TRUE at am__append_95 = plugins/maemo/libstrongswan-maemo.la
+ at USE_HA_TRUE@am__append_96 = plugins/ha
+ at MONOLITHIC_TRUE@@USE_HA_TRUE at am__append_97 = plugins/ha/libstrongswan-ha.la
+ at USE_KERNEL_PFKEY_TRUE@am__append_98 = plugins/kernel_pfkey
+ at MONOLITHIC_TRUE@@USE_KERNEL_PFKEY_TRUE at am__append_99 = plugins/kernel_pfkey/libstrongswan-kernel-pfkey.la
+ at USE_KERNEL_PFROUTE_TRUE@am__append_100 = plugins/kernel_pfroute
+ at MONOLITHIC_TRUE@@USE_KERNEL_PFROUTE_TRUE at am__append_101 = plugins/kernel_pfroute/libstrongswan-kernel-pfroute.la
+ at USE_KERNEL_NETLINK_TRUE@am__append_102 = plugins/kernel_netlink
+ at MONOLITHIC_TRUE@@USE_KERNEL_NETLINK_TRUE at am__append_103 = plugins/kernel_netlink/libstrongswan-kernel-netlink.la
+ at USE_KERNEL_LIBIPSEC_TRUE@am__append_104 = plugins/kernel_libipsec
+ at MONOLITHIC_TRUE@@USE_KERNEL_LIBIPSEC_TRUE at am__append_105 = plugins/kernel_libipsec/libstrongswan-kernel-libipsec.la
+ at USE_KERNEL_WFP_TRUE@am__append_106 = plugins/kernel_wfp
+ at MONOLITHIC_TRUE@@USE_KERNEL_WFP_TRUE at am__append_107 = plugins/kernel_wfp/libstrongswan-kernel-wfp.la
+ at USE_KERNEL_IPH_TRUE@am__append_108 = plugins/kernel_iph
+ at MONOLITHIC_TRUE@@USE_KERNEL_IPH_TRUE at am__append_109 = plugins/kernel_iph/libstrongswan-kernel-iph.la
+ at USE_WHITELIST_TRUE@am__append_110 = plugins/whitelist
+ at MONOLITHIC_TRUE@@USE_WHITELIST_TRUE at am__append_111 = plugins/whitelist/libstrongswan-whitelist.la
+ at USE_LOOKIP_TRUE@am__append_112 = plugins/lookip
+ at MONOLITHIC_TRUE@@USE_LOOKIP_TRUE at am__append_113 = plugins/lookip/libstrongswan-lookip.la
+ at USE_ERROR_NOTIFY_TRUE@am__append_114 = plugins/error_notify
+ at MONOLITHIC_TRUE@@USE_ERROR_NOTIFY_TRUE at am__append_115 = plugins/error_notify/libstrongswan-error-notify.la
+ at USE_CERTEXPIRE_TRUE@am__append_116 = plugins/certexpire
+ at MONOLITHIC_TRUE@@USE_CERTEXPIRE_TRUE at am__append_117 = plugins/certexpire/libstrongswan-certexpire.la
+ at USE_SYSTIME_FIX_TRUE@am__append_118 = plugins/systime_fix
+ at MONOLITHIC_TRUE@@USE_SYSTIME_FIX_TRUE at am__append_119 = plugins/systime_fix/libstrongswan-systime-fix.la
+ at USE_LED_TRUE@am__append_120 = plugins/led
+ at MONOLITHIC_TRUE@@USE_LED_TRUE at am__append_121 = plugins/led/libstrongswan-led.la
+ at USE_DUPLICHECK_TRUE@am__append_122 = plugins/duplicheck
+ at MONOLITHIC_TRUE@@USE_DUPLICHECK_TRUE at am__append_123 = plugins/duplicheck/libstrongswan-duplicheck.la
+ at USE_COUPLING_TRUE@am__append_124 = plugins/coupling
+ at MONOLITHIC_TRUE@@USE_COUPLING_TRUE at am__append_125 = plugins/coupling/libstrongswan-coupling.la
+ at USE_RADATTR_TRUE@am__append_126 = plugins/radattr
+ at MONOLITHIC_TRUE@@USE_RADATTR_TRUE at am__append_127 = plugins/radattr/libstrongswan-radattr.la
+ at USE_UCI_TRUE@am__append_128 = plugins/uci
+ at MONOLITHIC_TRUE@@USE_UCI_TRUE at am__append_129 = plugins/uci/libstrongswan-uci.la
+ at USE_ADDRBLOCK_TRUE@am__append_130 = plugins/addrblock
+ at MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE at am__append_131 = plugins/addrblock/libstrongswan-addrblock.la
+ at USE_UNITY_TRUE@am__append_132 = plugins/unity
+ at MONOLITHIC_TRUE@@USE_UNITY_TRUE at am__append_133 = plugins/unity/libstrongswan-unity.la
+ at USE_XAUTH_GENERIC_TRUE@am__append_134 = plugins/xauth_generic
+ at MONOLITHIC_TRUE@@USE_XAUTH_GENERIC_TRUE at am__append_135 = plugins/xauth_generic/libstrongswan-xauth-generic.la
+ at USE_XAUTH_EAP_TRUE@am__append_136 = plugins/xauth_eap
+ at MONOLITHIC_TRUE@@USE_XAUTH_EAP_TRUE at am__append_137 = plugins/xauth_eap/libstrongswan-xauth-eap.la
+ at USE_XAUTH_PAM_TRUE@am__append_138 = plugins/xauth_pam
+ at MONOLITHIC_TRUE@@USE_XAUTH_PAM_TRUE at am__append_139 = plugins/xauth_pam/libstrongswan-xauth-pam.la
+ at USE_XAUTH_NOAUTH_TRUE@am__append_140 = plugins/xauth_noauth
+ at MONOLITHIC_TRUE@@USE_XAUTH_NOAUTH_TRUE at am__append_141 = plugins/xauth_noauth/libstrongswan-xauth-noauth.la
+ at USE_RESOLVE_TRUE@am__append_142 = plugins/resolve
+ at MONOLITHIC_TRUE@@USE_RESOLVE_TRUE at am__append_143 = plugins/resolve/libstrongswan-resolve.la
+ at USE_ATTR_TRUE@am__append_144 = plugins/attr
+ at MONOLITHIC_TRUE@@USE_ATTR_TRUE at am__append_145 = plugins/attr/libstrongswan-attr.la
+ at USE_ATTR_SQL_TRUE@am__append_146 = plugins/attr_sql
+ at MONOLITHIC_TRUE@@USE_ATTR_SQL_TRUE at am__append_147 = plugins/attr_sql/libstrongswan-attr-sql.la
 subdir = src/libcharon
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/depcomp
@@ -325,47 +335,47 @@ LTLIBRARIES = $(ipseclib_LTLIBRARIES)
 am__DEPENDENCIES_1 =
 libcharon_la_DEPENDENCIES =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_1) $(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_37) $(am__append_39) \
-	$(am__append_41) $(am__append_43) $(am__append_45) \
-	$(am__append_47) $(am__append_49) $(am__append_51) \
-	$(am__append_53) $(am__append_54) $(am__append_56) \
-	$(am__append_58) $(am__append_60) $(am__append_62) \
-	$(am__append_64) $(am__append_66) $(am__append_68) \
-	$(am__append_70) $(am__append_72) $(am__append_73) \
-	$(am__append_74) $(am__append_76) $(am__append_78) \
-	$(am__append_79) $(am__append_81) $(am__append_83) \
-	$(am__append_85) $(am__append_87) $(am__append_89) \
-	$(am__append_91) $(am__append_93) $(am__append_95) \
-	$(am__append_97) $(am__append_99) $(am__append_101) \
-	$(am__append_103) $(am__append_105) $(am__append_107) \
-	$(am__append_109) $(am__append_111) $(am__append_113) \
-	$(am__append_115) $(am__append_117) $(am__append_119) \
-	$(am__append_121) $(am__append_123) $(am__append_125) \
-	$(am__append_127) $(am__append_129) $(am__append_131) \
-	$(am__append_133) $(am__append_135) $(am__append_137) \
-	$(am__append_139)
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) $(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_37) \
+	$(am__append_39) $(am__append_41) $(am__append_43) \
+	$(am__append_45) $(am__append_47) $(am__append_49) \
+	$(am__append_51) $(am__append_53) $(am__append_54) \
+	$(am__append_56) $(am__append_58) $(am__append_60) \
+	$(am__append_62) $(am__append_64) $(am__append_66) \
+	$(am__append_68) $(am__append_70) $(am__append_72) \
+	$(am__append_73) $(am__append_74) $(am__append_76) \
+	$(am__append_78) $(am__append_79) $(am__append_81) \
+	$(am__append_83) $(am__append_85) $(am__append_87) \
+	$(am__append_89) $(am__append_91) $(am__append_93) \
+	$(am__append_95) $(am__append_97) $(am__append_99) \
+	$(am__append_101) $(am__append_103) $(am__append_105) \
+	$(am__append_107) $(am__append_109) $(am__append_111) \
+	$(am__append_113) $(am__append_115) $(am__append_117) \
+	$(am__append_119) $(am__append_121) $(am__append_123) \
+	$(am__append_125) $(am__append_127) $(am__append_129) \
+	$(am__append_131) $(am__append_133) $(am__append_135) \
+	$(am__append_137) $(am__append_139) $(am__append_141) \
+	$(am__append_143) $(am__append_145) $(am__append_147)
 am__libcharon_la_SOURCES_DIST = attributes/attributes.c \
 	attributes/attributes.h attributes/attribute_provider.h \
 	attributes/attribute_handler.h attributes/attribute_manager.c \
 	attributes/attribute_manager.h attributes/mem_pool.c \
 	attributes/mem_pool.h bus/bus.c bus/bus.h \
 	bus/listeners/listener.h bus/listeners/logger.h \
-	bus/listeners/file_logger.c bus/listeners/file_logger.h \
-	config/backend_manager.c config/backend_manager.h \
-	config/backend.h config/child_cfg.c config/child_cfg.h \
-	config/ike_cfg.c config/ike_cfg.h config/peer_cfg.c \
-	config/peer_cfg.h config/proposal.c config/proposal.h \
-	control/controller.c control/controller.h daemon.c daemon.h \
-	encoding/generator.c encoding/generator.h encoding/message.c \
-	encoding/message.h encoding/parser.c encoding/parser.h \
-	encoding/payloads/auth_payload.c \
+	bus/listeners/custom_logger.h bus/listeners/file_logger.c \
+	bus/listeners/file_logger.h config/backend_manager.c \
+	config/backend_manager.h config/backend.h config/child_cfg.c \
+	config/child_cfg.h config/ike_cfg.c config/ike_cfg.h \
+	config/peer_cfg.c config/peer_cfg.h config/proposal.c \
+	config/proposal.h control/controller.c control/controller.h \
+	daemon.c daemon.h encoding/generator.c encoding/generator.h \
+	encoding/message.c encoding/message.h encoding/parser.c \
+	encoding/parser.h encoding/payloads/auth_payload.c \
 	encoding/payloads/auth_payload.h \
 	encoding/payloads/cert_payload.c \
 	encoding/payloads/cert_payload.h \
@@ -407,7 +417,10 @@ am__libcharon_la_SOURCES_DIST = attributes/attributes.c \
 	encoding/payloads/hash_payload.c \
 	encoding/payloads/hash_payload.h \
 	encoding/payloads/fragment_payload.c \
-	encoding/payloads/fragment_payload.h kernel/kernel_handler.c \
+	encoding/payloads/fragment_payload.h kernel/kernel_interface.c \
+	kernel/kernel_interface.h kernel/kernel_ipsec.c \
+	kernel/kernel_ipsec.h kernel/kernel_net.c kernel/kernel_net.h \
+	kernel/kernel_listener.h kernel/kernel_handler.c \
 	kernel/kernel_handler.h network/receiver.c network/receiver.h \
 	network/sender.c network/sender.h network/socket.c \
 	network/socket.h network/socket_manager.c \
@@ -420,6 +433,7 @@ am__libcharon_la_SOURCES_DIST = attributes/attributes.c \
 	processing/jobs/migrate_job.c processing/jobs/migrate_job.h \
 	processing/jobs/process_message_job.c \
 	processing/jobs/process_message_job.h \
+	processing/jobs/redirect_job.c processing/jobs/redirect_job.h \
 	processing/jobs/rekey_child_sa_job.c \
 	processing/jobs/rekey_child_sa_job.h \
 	processing/jobs/rekey_ike_sa_job.c \
@@ -449,7 +463,8 @@ am__libcharon_la_SOURCES_DIST = attributes/attributes.c \
 	sa/ike_sa_manager.h sa/child_sa_manager.c \
 	sa/child_sa_manager.h sa/task_manager.h sa/task_manager.c \
 	sa/shunt_manager.c sa/shunt_manager.h sa/trap_manager.c \
-	sa/trap_manager.h sa/task.c sa/task.h sa/ikev2/keymat_v2.c \
+	sa/trap_manager.h sa/redirect_provider.h sa/redirect_manager.c \
+	sa/redirect_manager.h sa/task.c sa/task.h sa/ikev2/keymat_v2.c \
 	sa/ikev2/keymat_v2.h sa/ikev2/task_manager_v2.c \
 	sa/ikev2/task_manager_v2.h \
 	sa/ikev2/authenticators/eap_authenticator.c \
@@ -474,9 +489,12 @@ am__libcharon_la_SOURCES_DIST = attributes/attributes.c \
 	sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \
 	sa/ikev2/tasks/ike_reauth_complete.c \
 	sa/ikev2/tasks/ike_reauth_complete.h \
+	sa/ikev2/tasks/ike_redirect.c sa/ikev2/tasks/ike_redirect.h \
 	sa/ikev2/tasks/ike_auth_lifetime.c \
 	sa/ikev2/tasks/ike_auth_lifetime.h sa/ikev2/tasks/ike_vendor.c \
-	sa/ikev2/tasks/ike_vendor.h sa/ikev1/keymat_v1.c \
+	sa/ikev2/tasks/ike_vendor.h \
+	sa/ikev2/tasks/ike_verify_peer_cert.c \
+	sa/ikev2/tasks/ike_verify_peer_cert.h sa/ikev1/keymat_v1.c \
 	sa/ikev1/keymat_v1.h sa/ikev1/task_manager_v1.c \
 	sa/ikev1/task_manager_v1.h \
 	sa/ikev1/authenticators/psk_v1_authenticator.c \
@@ -535,8 +553,10 @@ am__dirstamp = $(am__leading_dot)dirstamp
 @USE_IKEV2_TRUE@	sa/ikev2/tasks/ike_rekey.lo \
 @USE_IKEV2_TRUE@	sa/ikev2/tasks/ike_reauth.lo \
 @USE_IKEV2_TRUE@	sa/ikev2/tasks/ike_reauth_complete.lo \
+ at USE_IKEV2_TRUE@	sa/ikev2/tasks/ike_redirect.lo \
 @USE_IKEV2_TRUE@	sa/ikev2/tasks/ike_auth_lifetime.lo \
- at USE_IKEV2_TRUE@	sa/ikev2/tasks/ike_vendor.lo
+ at USE_IKEV2_TRUE@	sa/ikev2/tasks/ike_vendor.lo \
+ at USE_IKEV2_TRUE@	sa/ikev2/tasks/ike_verify_peer_cert.lo
 @USE_IKEV1_TRUE at am__objects_2 = sa/ikev1/keymat_v1.lo \
 @USE_IKEV1_TRUE@	sa/ikev1/task_manager_v1.lo \
 @USE_IKEV1_TRUE@	sa/ikev1/authenticators/psk_v1_authenticator.lo \
@@ -595,13 +615,16 @@ am_libcharon_la_OBJECTS = attributes/attributes.lo \
 	encoding/payloads/unknown_payload.lo \
 	encoding/payloads/vendor_id_payload.lo \
 	encoding/payloads/hash_payload.lo \
-	encoding/payloads/fragment_payload.lo kernel/kernel_handler.lo \
+	encoding/payloads/fragment_payload.lo \
+	kernel/kernel_interface.lo kernel/kernel_ipsec.lo \
+	kernel/kernel_net.lo kernel/kernel_handler.lo \
 	network/receiver.lo network/sender.lo network/socket.lo \
 	network/socket_manager.lo processing/jobs/acquire_job.lo \
 	processing/jobs/delete_child_sa_job.lo \
 	processing/jobs/delete_ike_sa_job.lo \
 	processing/jobs/migrate_job.lo \
 	processing/jobs/process_message_job.lo \
+	processing/jobs/redirect_job.lo \
 	processing/jobs/rekey_child_sa_job.lo \
 	processing/jobs/rekey_ike_sa_job.lo \
 	processing/jobs/retransmit_job.lo \
@@ -616,8 +639,9 @@ am_libcharon_la_OBJECTS = attributes/attributes.lo \
 	sa/xauth/xauth_manager.lo sa/authenticator.lo sa/child_sa.lo \
 	sa/ike_sa.lo sa/ike_sa_id.lo sa/keymat.lo sa/ike_sa_manager.lo \
 	sa/child_sa_manager.lo sa/task_manager.lo sa/shunt_manager.lo \
-	sa/trap_manager.lo sa/task.lo $(am__objects_1) \
-	$(am__objects_2) $(am__objects_3) $(am__objects_4)
+	sa/trap_manager.lo sa/redirect_manager.lo sa/task.lo \
+	$(am__objects_1) $(am__objects_2) $(am__objects_3) \
+	$(am__objects_4)
 libcharon_la_OBJECTS = $(am_libcharon_la_OBJECTS)
 AM_V_lt = $(am__v_lt_ at AM_V@)
 am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
@@ -712,12 +736,14 @@ DIST_SUBDIRS = . plugins/load_tester plugins/socket_default \
 	plugins/eap_tls plugins/eap_ttls plugins/eap_peap \
 	plugins/eap_tnc plugins/tnc_ifmap plugins/tnc_pdp \
 	plugins/medsrv plugins/medcli plugins/dhcp plugins/osx_attr \
-	plugins/android_dns plugins/android_log plugins/maemo \
-	plugins/ha plugins/kernel_libipsec plugins/kernel_wfp \
-	plugins/kernel_iph plugins/whitelist plugins/lookip \
-	plugins/error_notify plugins/certexpire plugins/systime_fix \
-	plugins/led plugins/duplicheck plugins/coupling \
-	plugins/radattr plugins/uci plugins/addrblock plugins/unity \
+	plugins/p_cscf plugins/android_dns plugins/android_log \
+	plugins/maemo plugins/ha plugins/kernel_pfkey \
+	plugins/kernel_pfroute plugins/kernel_netlink \
+	plugins/kernel_libipsec plugins/kernel_wfp plugins/kernel_iph \
+	plugins/whitelist plugins/lookip plugins/error_notify \
+	plugins/certexpire plugins/systime_fix plugins/led \
+	plugins/duplicheck plugins/coupling plugins/radattr \
+	plugins/uci plugins/addrblock plugins/unity \
 	plugins/xauth_generic plugins/xauth_eap plugins/xauth_pam \
 	plugins/xauth_noauth plugins/resolve plugins/attr \
 	plugins/attr_sql tests
@@ -959,6 +985,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -978,15 +1006,15 @@ libcharon_la_SOURCES = attributes/attributes.c attributes/attributes.h \
 	attributes/attribute_manager.c attributes/attribute_manager.h \
 	attributes/mem_pool.c attributes/mem_pool.h bus/bus.c \
 	bus/bus.h bus/listeners/listener.h bus/listeners/logger.h \
-	bus/listeners/file_logger.c bus/listeners/file_logger.h \
-	config/backend_manager.c config/backend_manager.h \
-	config/backend.h config/child_cfg.c config/child_cfg.h \
-	config/ike_cfg.c config/ike_cfg.h config/peer_cfg.c \
-	config/peer_cfg.h config/proposal.c config/proposal.h \
-	control/controller.c control/controller.h daemon.c daemon.h \
-	encoding/generator.c encoding/generator.h encoding/message.c \
-	encoding/message.h encoding/parser.c encoding/parser.h \
-	encoding/payloads/auth_payload.c \
+	bus/listeners/custom_logger.h bus/listeners/file_logger.c \
+	bus/listeners/file_logger.h config/backend_manager.c \
+	config/backend_manager.h config/backend.h config/child_cfg.c \
+	config/child_cfg.h config/ike_cfg.c config/ike_cfg.h \
+	config/peer_cfg.c config/peer_cfg.h config/proposal.c \
+	config/proposal.h control/controller.c control/controller.h \
+	daemon.c daemon.h encoding/generator.c encoding/generator.h \
+	encoding/message.c encoding/message.h encoding/parser.c \
+	encoding/parser.h encoding/payloads/auth_payload.c \
 	encoding/payloads/auth_payload.h \
 	encoding/payloads/cert_payload.c \
 	encoding/payloads/cert_payload.h \
@@ -1028,7 +1056,10 @@ libcharon_la_SOURCES = attributes/attributes.c attributes/attributes.h \
 	encoding/payloads/hash_payload.c \
 	encoding/payloads/hash_payload.h \
 	encoding/payloads/fragment_payload.c \
-	encoding/payloads/fragment_payload.h kernel/kernel_handler.c \
+	encoding/payloads/fragment_payload.h kernel/kernel_interface.c \
+	kernel/kernel_interface.h kernel/kernel_ipsec.c \
+	kernel/kernel_ipsec.h kernel/kernel_net.c kernel/kernel_net.h \
+	kernel/kernel_listener.h kernel/kernel_handler.c \
 	kernel/kernel_handler.h network/receiver.c network/receiver.h \
 	network/sender.c network/sender.h network/socket.c \
 	network/socket.h network/socket_manager.c \
@@ -1041,6 +1072,7 @@ libcharon_la_SOURCES = attributes/attributes.c attributes/attributes.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/redirect_job.c processing/jobs/redirect_job.h \
 	processing/jobs/rekey_child_sa_job.c \
 	processing/jobs/rekey_child_sa_job.h \
 	processing/jobs/rekey_ike_sa_job.c \
@@ -1070,12 +1102,12 @@ libcharon_la_SOURCES = attributes/attributes.c attributes/attributes.h \
 	sa/ike_sa_manager.h sa/child_sa_manager.c \
 	sa/child_sa_manager.h sa/task_manager.h sa/task_manager.c \
 	sa/shunt_manager.c sa/shunt_manager.h sa/trap_manager.c \
-	sa/trap_manager.h sa/task.c sa/task.h $(am__append_1) \
+	sa/trap_manager.h sa/redirect_provider.h sa/redirect_manager.c \
+	sa/redirect_manager.h sa/task.c sa/task.h $(am__append_1) \
 	$(am__append_2) $(am__append_3) $(am__append_5)
 AM_CPPFLAGS = \
 	-I${linux_headers} \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_DIR=\"${ipsecdir}\" \
 	-DIPSEC_PIDDIR=\"${piddir}\"
@@ -1084,32 +1116,33 @@ AM_LDFLAGS = \
   -no-undefined
 
 libcharon_la_LIBADD =  \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la -lm $(PTHREADLIB) \
-	$(DLLIB) $(SOCKLIB) $(am__append_4) $(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_37) \
-	$(am__append_39) $(am__append_41) $(am__append_43) \
-	$(am__append_45) $(am__append_47) $(am__append_49) \
-	$(am__append_51) $(am__append_53) $(am__append_54) \
-	$(am__append_56) $(am__append_58) $(am__append_60) \
-	$(am__append_62) $(am__append_64) $(am__append_66) \
-	$(am__append_68) $(am__append_70) $(am__append_72) \
-	$(am__append_73) $(am__append_74) $(am__append_76) \
-	$(am__append_78) $(am__append_79) $(am__append_81) \
-	$(am__append_83) $(am__append_85) $(am__append_87) \
-	$(am__append_89) $(am__append_91) $(am__append_93) \
-	$(am__append_95) $(am__append_97) $(am__append_99) \
-	$(am__append_101) $(am__append_103) $(am__append_105) \
-	$(am__append_107) $(am__append_109) $(am__append_111) \
-	$(am__append_113) $(am__append_115) $(am__append_117) \
-	$(am__append_119) $(am__append_121) $(am__append_123) \
-	$(am__append_125) $(am__append_127) $(am__append_129) \
-	$(am__append_131) $(am__append_133) $(am__append_135) \
-	$(am__append_137) $(am__append_139)
+	$(top_builddir)/src/libstrongswan/libstrongswan.la -lm \
+	$(PTHREADLIB) $(DLLIB) $(SOCKLIB) $(am__append_4) \
+	$(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_37) $(am__append_39) $(am__append_41) \
+	$(am__append_43) $(am__append_45) $(am__append_47) \
+	$(am__append_49) $(am__append_51) $(am__append_53) \
+	$(am__append_54) $(am__append_56) $(am__append_58) \
+	$(am__append_60) $(am__append_62) $(am__append_64) \
+	$(am__append_66) $(am__append_68) $(am__append_70) \
+	$(am__append_72) $(am__append_73) $(am__append_74) \
+	$(am__append_76) $(am__append_78) $(am__append_79) \
+	$(am__append_81) $(am__append_83) $(am__append_85) \
+	$(am__append_87) $(am__append_89) $(am__append_91) \
+	$(am__append_93) $(am__append_95) $(am__append_97) \
+	$(am__append_99) $(am__append_101) $(am__append_103) \
+	$(am__append_105) $(am__append_107) $(am__append_109) \
+	$(am__append_111) $(am__append_113) $(am__append_115) \
+	$(am__append_117) $(am__append_119) $(am__append_121) \
+	$(am__append_123) $(am__append_125) $(am__append_127) \
+	$(am__append_129) $(am__append_131) $(am__append_133) \
+	$(am__append_135) $(am__append_137) $(am__append_139) \
+	$(am__append_141) $(am__append_143) $(am__append_145) \
+	$(am__append_147)
 EXTRA_DIST = Android.mk
 @MONOLITHIC_FALSE at SUBDIRS = . $(am__append_6) $(am__append_8) \
 @MONOLITHIC_FALSE@	$(am__append_10) $(am__append_12) \
@@ -1143,7 +1176,9 @@ EXTRA_DIST = Android.mk
 @MONOLITHIC_FALSE@	$(am__append_126) $(am__append_128) \
 @MONOLITHIC_FALSE@	$(am__append_130) $(am__append_132) \
 @MONOLITHIC_FALSE@	$(am__append_134) $(am__append_136) \
- at MONOLITHIC_FALSE@	$(am__append_138) tests
+ at MONOLITHIC_FALSE@	$(am__append_138) $(am__append_140) \
+ at MONOLITHIC_FALSE@	$(am__append_142) $(am__append_144) \
+ at MONOLITHIC_FALSE@	$(am__append_146) tests
 
 # build optional plugins
 ########################
@@ -1179,7 +1214,9 @@ EXTRA_DIST = Android.mk
 @MONOLITHIC_TRUE@	$(am__append_126) $(am__append_128) \
 @MONOLITHIC_TRUE@	$(am__append_130) $(am__append_132) \
 @MONOLITHIC_TRUE@	$(am__append_134) $(am__append_136) \
- at MONOLITHIC_TRUE@	$(am__append_138) . tests
+ at MONOLITHIC_TRUE@	$(am__append_138) $(am__append_140) \
+ at MONOLITHIC_TRUE@	$(am__append_142) $(am__append_144) \
+ at MONOLITHIC_TRUE@	$(am__append_146) . tests
 all: all-recursive
 
 .SUFFIXES:
@@ -1386,6 +1423,12 @@ kernel/$(am__dirstamp):
 kernel/$(DEPDIR)/$(am__dirstamp):
 	@$(MKDIR_P) kernel/$(DEPDIR)
 	@: > kernel/$(DEPDIR)/$(am__dirstamp)
+kernel/kernel_interface.lo: kernel/$(am__dirstamp) \
+	kernel/$(DEPDIR)/$(am__dirstamp)
+kernel/kernel_ipsec.lo: kernel/$(am__dirstamp) \
+	kernel/$(DEPDIR)/$(am__dirstamp)
+kernel/kernel_net.lo: kernel/$(am__dirstamp) \
+	kernel/$(DEPDIR)/$(am__dirstamp)
 kernel/kernel_handler.lo: kernel/$(am__dirstamp) \
 	kernel/$(DEPDIR)/$(am__dirstamp)
 network/$(am__dirstamp):
@@ -1420,6 +1463,8 @@ processing/jobs/migrate_job.lo: processing/jobs/$(am__dirstamp) \
 processing/jobs/process_message_job.lo:  \
 	processing/jobs/$(am__dirstamp) \
 	processing/jobs/$(DEPDIR)/$(am__dirstamp)
+processing/jobs/redirect_job.lo: processing/jobs/$(am__dirstamp) \
+	processing/jobs/$(DEPDIR)/$(am__dirstamp)
 processing/jobs/rekey_child_sa_job.lo:  \
 	processing/jobs/$(am__dirstamp) \
 	processing/jobs/$(DEPDIR)/$(am__dirstamp)
@@ -1483,6 +1528,8 @@ sa/child_sa_manager.lo: sa/$(am__dirstamp) \
 sa/task_manager.lo: sa/$(am__dirstamp) sa/$(DEPDIR)/$(am__dirstamp)
 sa/shunt_manager.lo: sa/$(am__dirstamp) sa/$(DEPDIR)/$(am__dirstamp)
 sa/trap_manager.lo: sa/$(am__dirstamp) sa/$(DEPDIR)/$(am__dirstamp)
+sa/redirect_manager.lo: sa/$(am__dirstamp) \
+	sa/$(DEPDIR)/$(am__dirstamp)
 sa/task.lo: sa/$(am__dirstamp) sa/$(DEPDIR)/$(am__dirstamp)
 sa/ikev2/$(am__dirstamp):
 	@$(MKDIR_P) sa/ikev2
@@ -1545,10 +1592,15 @@ sa/ikev2/tasks/ike_reauth.lo: sa/ikev2/tasks/$(am__dirstamp) \
 	sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp)
 sa/ikev2/tasks/ike_reauth_complete.lo: sa/ikev2/tasks/$(am__dirstamp) \
 	sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp)
+sa/ikev2/tasks/ike_redirect.lo: sa/ikev2/tasks/$(am__dirstamp) \
+	sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp)
 sa/ikev2/tasks/ike_auth_lifetime.lo: sa/ikev2/tasks/$(am__dirstamp) \
 	sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp)
 sa/ikev2/tasks/ike_vendor.lo: sa/ikev2/tasks/$(am__dirstamp) \
 	sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp)
+sa/ikev2/tasks/ike_verify_peer_cert.lo:  \
+	sa/ikev2/tasks/$(am__dirstamp) \
+	sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp)
 sa/ikev1/$(am__dirstamp):
 	@$(MKDIR_P) sa/ikev1
 	@: > sa/ikev1/$(am__dirstamp)
@@ -1720,6 +1772,9 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at encoding/payloads/$(DEPDIR)/unknown_payload.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at encoding/payloads/$(DEPDIR)/vendor_id_payload.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at kernel/$(DEPDIR)/kernel_handler.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at kernel/$(DEPDIR)/kernel_interface.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at kernel/$(DEPDIR)/kernel_ipsec.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at kernel/$(DEPDIR)/kernel_net.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at network/$(DEPDIR)/receiver.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at network/$(DEPDIR)/sender.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at network/$(DEPDIR)/socket.Plo at am__quote@
@@ -1735,6 +1790,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at processing/jobs/$(DEPDIR)/mediation_job.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at processing/jobs/$(DEPDIR)/migrate_job.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at processing/jobs/$(DEPDIR)/process_message_job.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at processing/jobs/$(DEPDIR)/redirect_job.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at processing/jobs/$(DEPDIR)/rekey_child_sa_job.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at processing/jobs/$(DEPDIR)/rekey_ike_sa_job.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at processing/jobs/$(DEPDIR)/retransmit_job.Plo at am__quote@
@@ -1751,6 +1807,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at sa/$(DEPDIR)/ike_sa_id.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at sa/$(DEPDIR)/ike_sa_manager.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at sa/$(DEPDIR)/keymat.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at sa/$(DEPDIR)/redirect_manager.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at sa/$(DEPDIR)/shunt_manager.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at sa/$(DEPDIR)/task.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at sa/$(DEPDIR)/task_manager.Plo at am__quote@
@@ -1799,8 +1856,10 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at sa/ikev2/tasks/$(DEPDIR)/ike_natd.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at sa/ikev2/tasks/$(DEPDIR)/ike_reauth.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at sa/ikev2/tasks/$(DEPDIR)/ike_reauth_complete.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at sa/ikev2/tasks/$(DEPDIR)/ike_redirect.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at sa/ikev2/tasks/$(DEPDIR)/ike_rekey.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at sa/ikev2/tasks/$(DEPDIR)/ike_vendor.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at sa/ikev2/tasks/$(DEPDIR)/ike_verify_peer_cert.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at sa/xauth/$(DEPDIR)/xauth_manager.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at sa/xauth/$(DEPDIR)/xauth_method.Plo at am__quote@
 
diff --git a/src/libcharon/attributes/attributes.c b/src/libcharon/attributes/attributes.c
index 9fabcf4..0f28d55 100644
--- a/src/libcharon/attributes/attributes.c
+++ b/src/libcharon/attributes/attributes.c
@@ -17,7 +17,7 @@
 
 #include "attributes.h"
 
-ENUM_BEGIN(configuration_attribute_type_names, INTERNAL_IP4_ADDRESS, HOME_AGENT_ADDRESS,
+ENUM_BEGIN(configuration_attribute_type_names, INTERNAL_IP4_ADDRESS, P_CSCF_IP6_ADDRESS,
 	"INTERNAL_IP4_ADDRESS",
 	"INTERNAL_IP4_NETMASK",
 	"INTERNAL_IP4_DNS",
@@ -36,8 +36,10 @@ ENUM_BEGIN(configuration_attribute_type_names, INTERNAL_IP4_ADDRESS, HOME_AGENT_
 	"MIP6_HOME_PREFIX",
 	"INTERNAL_IP6_LINK",
 	"INTERNAL_IP6_PREFIX",
-	"HOME_AGENT_ADDRESS");
-ENUM_NEXT(configuration_attribute_type_names, XAUTH_TYPE, XAUTH_ANSWER, HOME_AGENT_ADDRESS,
+	"HOME_AGENT_ADDRESS",
+	"P_CSCF_IP4_ADDRESS",
+	"P_CSCF_IP6_ADDRESS");
+ENUM_NEXT(configuration_attribute_type_names, XAUTH_TYPE, XAUTH_ANSWER, P_CSCF_IP6_ADDRESS,
 	"XAUTH_TYPE",
 	"XAUTH_USER_NAME",
 	"XAUTH_USER_PASSWORD",
@@ -65,7 +67,7 @@ ENUM_NEXT(configuration_attribute_type_names, UNITY_BANNER, UNITY_DDNS_HOSTNAME,
 	"UNITY_DDNS_HOSTNAME");
 ENUM_END(configuration_attribute_type_names, UNITY_DDNS_HOSTNAME);
 
-ENUM_BEGIN(configuration_attribute_type_short_names, INTERNAL_IP4_ADDRESS, HOME_AGENT_ADDRESS,
+ENUM_BEGIN(configuration_attribute_type_short_names, INTERNAL_IP4_ADDRESS, P_CSCF_IP6_ADDRESS,
 	"ADDR",
 	"MASK",
 	"DNS",
@@ -84,8 +86,10 @@ ENUM_BEGIN(configuration_attribute_type_short_names, INTERNAL_IP4_ADDRESS, HOME_
 	"MIP6HPFX",
 	"LINK6",
 	"PFX6",
-	"HOA");
-ENUM_NEXT(configuration_attribute_type_short_names, XAUTH_TYPE, XAUTH_ANSWER, HOME_AGENT_ADDRESS,
+	"HOA",
+	"PCSCF4",
+	"PCSCF6");
+ENUM_NEXT(configuration_attribute_type_short_names, XAUTH_TYPE, XAUTH_ANSWER, P_CSCF_IP6_ADDRESS,
 	"X_TYPE",
 	"X_USER",
 	"X_PWD",
diff --git a/src/libcharon/attributes/attributes.h b/src/libcharon/attributes/attributes.h
index 5d1e9f9..dd1db4f 100644
--- a/src/libcharon/attributes/attributes.h
+++ b/src/libcharon/attributes/attributes.h
@@ -49,6 +49,9 @@ enum configuration_attribute_type_t {
 	INTERNAL_IP6_LINK       = 17,
 	INTERNAL_IP6_PREFIX     = 18,
 	HOME_AGENT_ADDRESS		= 19,
+	/* RFC 7651 */
+	P_CSCF_IP4_ADDRESS		= 20,
+	P_CSCF_IP6_ADDRESS		= 21,
 	/* XAUTH attributes */
 	XAUTH_TYPE              = 16520,
 	XAUTH_USER_NAME         = 16521,
diff --git a/src/libcharon/attributes/mem_pool.c b/src/libcharon/attributes/mem_pool.c
index 2796682..833c3e9 100644
--- a/src/libcharon/attributes/mem_pool.c
+++ b/src/libcharon/attributes/mem_pool.c
@@ -17,7 +17,6 @@
 #include "mem_pool.h"
 
 #include <library.h>
-#include <hydra.h>
 #include <utils/debug.h>
 #include <collections/hashtable.h>
 #include <collections/array.h>
diff --git a/src/libcharon/bus/listeners/custom_logger.h b/src/libcharon/bus/listeners/custom_logger.h
new file mode 100644
index 0000000..a256ad1
--- /dev/null
+++ b/src/libcharon/bus/listeners/custom_logger.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2016 secunet Security Networks AG
+ * Copyright (C) 2016 Thomas Egerer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * @defgroup custom_logger custom_logger
+ * @{ @ingroup listeners
+ */
+
+#ifndef CUSTOM_LOGGER_H_
+#define CUSTOM_LOGGER_H_
+
+#include <bus/listeners/logger.h>
+
+typedef struct custom_logger_t custom_logger_t;
+
+/**
+ * Custom logger which implements listener_t.
+ */
+struct custom_logger_t {
+
+	/**
+	 * Implements the logger_t interface.
+	 */
+	logger_t logger;
+
+	/**
+	 * Set the loglevel for a debug group.
+	 *
+	 * @param group		debug group to set
+	 * @param level		max level to log (0..4)
+	 */
+	void (*set_level) (custom_logger_t *this, debug_t group, level_t level);
+
+	/**
+	 * Destroy the custom_logger_t object.
+	 */
+	void (*destroy) (custom_logger_t *this);
+};
+
+/**
+ * Prototype for custom logger construction function pointer.
+ */
+typedef custom_logger_t *(*custom_logger_constructor_t)(const char *name);
+
+#endif /** CUSTOM_LOGGER_H_ @}*/
diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c
index ed7c0d4..3d3c741 100644
--- a/src/libcharon/config/child_cfg.c
+++ b/src/libcharon/config/child_cfg.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2009 Tobias Brunner
+ * Copyright (C) 2008-2015 Tobias Brunner
  * Copyright (C) 2005-2007 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
@@ -531,6 +531,57 @@ METHOD(child_cfg_t, install_policy, bool,
 	return this->install_policy;
 }
 
+#define LT_PART_EQUALS(a, b) ({ a.life == b.life && a.rekey == b.rekey && a.jitter == b.jitter; })
+#define LIFETIME_EQUALS(a, b) ({  LT_PART_EQUALS(a.time, b.time) && LT_PART_EQUALS(a.bytes, b.bytes) && LT_PART_EQUALS(a.packets, b.packets); })
+
+METHOD(child_cfg_t, equals, bool,
+	private_child_cfg_t *this, child_cfg_t *other_pub)
+{
+	private_child_cfg_t *other = (private_child_cfg_t*)other_pub;
+
+	if (this == other)
+	{
+		return TRUE;
+	}
+	if (this->public.equals != other->public.equals)
+	{
+		return FALSE;
+	}
+	if (!this->proposals->equals_offset(this->proposals, other->proposals,
+										offsetof(proposal_t, equals)))
+	{
+		return FALSE;
+	}
+	if (!this->my_ts->equals_offset(this->my_ts, other->my_ts,
+									offsetof(traffic_selector_t, equals)))
+	{
+		return FALSE;
+	}
+	if (!this->other_ts->equals_offset(this->other_ts, other->other_ts,
+									   offsetof(traffic_selector_t, equals)))
+	{
+		return FALSE;
+	}
+	return this->hostaccess == other->hostaccess &&
+		this->mode == other->mode &&
+		this->start_action == other->start_action &&
+		this->dpd_action == other->dpd_action &&
+		this->close_action == other->close_action &&
+		LIFETIME_EQUALS(this->lifetime, other->lifetime) &&
+		this->use_ipcomp == other->use_ipcomp &&
+		this->inactivity == other->inactivity &&
+		this->reqid == other->reqid &&
+		this->mark_in.value == other->mark_in.value &&
+		this->mark_in.mask == other->mark_in.mask &&
+		this->mark_out.value == other->mark_out.value &&
+		this->mark_out.mask == other->mark_out.mask &&
+		this->tfc == other->tfc &&
+		this->replay_window == other->replay_window &&
+		this->proxy_mode == other->proxy_mode &&
+		this->install_policy == other->install_policy &&
+		streq(this->updown, other->updown);
+}
+
 METHOD(child_cfg_t, get_ref, child_cfg_t*,
 	private_child_cfg_t *this)
 {
@@ -593,6 +644,7 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
 			.set_replay_window = _set_replay_window,
 			.use_proxy_mode = _use_proxy_mode,
 			.install_policy = _install_policy,
+			.equals = _equals,
 			.get_ref = _get_ref,
 			.destroy = _destroy,
 		},
diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h
index 9f7a92b..22641f7 100644
--- a/src/libcharon/config/child_cfg.h
+++ b/src/libcharon/config/child_cfg.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2009 Tobias Brunner
+ * Copyright (C) 2008-2015 Tobias Brunner
  * Copyright (C) 2005-2007 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
@@ -274,6 +274,14 @@ struct child_cfg_t {
 	bool (*install_policy)(child_cfg_t *this);
 
 	/**
+	 * Check if two child_cfg objects are equal.
+	 *
+	 * @param other			candidate to check for equality against this
+	 * @return				TRUE if equal
+	 */
+	bool (*equals)(child_cfg_t *this, child_cfg_t *other);
+
+	/**
 	 * Increase the reference count.
 	 *
 	 * @return				reference to this
diff --git a/src/libcharon/config/ike_cfg.c b/src/libcharon/config/ike_cfg.c
index dee9e4c..a720e14 100644
--- a/src/libcharon/config/ike_cfg.c
+++ b/src/libcharon/config/ike_cfg.c
@@ -371,9 +371,6 @@ METHOD(ike_cfg_t, equals, bool,
 	private_ike_cfg_t *this, ike_cfg_t *other_public)
 {
 	private_ike_cfg_t *other = (private_ike_cfg_t*)other_public;
-	enumerator_t *e1, *e2;
-	proposal_t *p1, *p2;
-	bool eq = TRUE;
 
 	if (this == other)
 	{
@@ -383,25 +380,12 @@ METHOD(ike_cfg_t, equals, bool,
 	{
 		return FALSE;
 	}
-	if (this->proposals->get_count(this->proposals) !=
-		other->proposals->get_count(other->proposals))
+	if (!this->proposals->equals_offset(this->proposals, other->proposals,
+										offsetof(proposal_t, equals)))
 	{
 		return FALSE;
 	}
-	e1 = this->proposals->create_enumerator(this->proposals);
-	e2 = other->proposals->create_enumerator(other->proposals);
-	while (e1->enumerate(e1, &p1) && e2->enumerate(e2, &p2))
-	{
-		if (!p1->equals(p1, p2))
-		{
-			eq = FALSE;
-			break;
-		}
-	}
-	e1->destroy(e1);
-	e2->destroy(e2);
-
-	return (eq &&
+	return
 		this->version == other->version &&
 		this->certreq == other->certreq &&
 		this->force_encap == other->force_encap &&
@@ -409,7 +393,7 @@ METHOD(ike_cfg_t, equals, bool,
 		streq(this->me, other->me) &&
 		streq(this->other, other->other) &&
 		this->my_port == other->my_port &&
-		this->other_port == other->other_port);
+		this->other_port == other->other_port;
 }
 
 METHOD(ike_cfg_t, get_ref, ike_cfg_t*,
diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c
index aa2a39c..d28a795 100644
--- a/src/libcharon/config/peer_cfg.c
+++ b/src/libcharon/config/peer_cfg.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Tobias Brunner
+ * Copyright (C) 2007-2015 Tobias Brunner
  * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
@@ -200,6 +200,117 @@ METHOD(peer_cfg_t, add_child_cfg, void,
 	this->mutex->unlock(this->mutex);
 }
 
+typedef struct {
+	enumerator_t public;
+	linked_list_t *removed;
+	linked_list_t *added;
+	enumerator_t *wrapped;
+	bool add;
+} child_cfgs_replace_enumerator_t;
+
+METHOD(enumerator_t, child_cfgs_replace_enumerate, bool,
+	child_cfgs_replace_enumerator_t *this, child_cfg_t **chd, bool *added)
+{
+	child_cfg_t *child_cfg;
+
+	if (!this->wrapped)
+	{
+		this->wrapped = this->removed->create_enumerator(this->removed);
+	}
+	while (TRUE)
+	{
+		if (this->wrapped->enumerate(this->wrapped, &child_cfg))
+		{
+			if (chd)
+			{
+				*chd = child_cfg;
+			}
+			if (added)
+			{
+				*added = this->add;
+			}
+			return TRUE;
+		}
+		if (this->add)
+		{
+			break;
+		}
+		this->wrapped = this->added->create_enumerator(this->added);
+		this->add = TRUE;
+	}
+	return FALSE;
+}
+
+METHOD(enumerator_t, child_cfgs_replace_enumerator_destroy, void,
+	child_cfgs_replace_enumerator_t *this)
+{
+	DESTROY_IF(this->wrapped);
+	this->removed->destroy_offset(this->removed, offsetof(child_cfg_t, destroy));
+	this->added->destroy_offset(this->added, offsetof(child_cfg_t, destroy));
+	free(this);
+}
+
+METHOD(peer_cfg_t, replace_child_cfgs, enumerator_t*,
+	private_peer_cfg_t *this, peer_cfg_t *other_pub)
+{
+	private_peer_cfg_t *other = (private_peer_cfg_t*)other_pub;
+	linked_list_t *removed, *added;
+	enumerator_t *mine, *others;
+	child_cfg_t *my_cfg, *other_cfg;
+	child_cfgs_replace_enumerator_t *enumerator;
+	bool found;
+
+	removed = linked_list_create();
+
+	other->mutex->lock(other->mutex);
+	added = linked_list_create_from_enumerator(
+					other->child_cfgs->create_enumerator(other->child_cfgs));
+	added->invoke_offset(added, offsetof(child_cfg_t, get_ref));
+	other->mutex->unlock(other->mutex);
+
+	this->mutex->lock(this->mutex);
+	others = added->create_enumerator(added);
+	mine = this->child_cfgs->create_enumerator(this->child_cfgs);
+	while (mine->enumerate(mine, &my_cfg))
+	{
+		found = FALSE;
+		while (others->enumerate(others, &other_cfg))
+		{
+			if (my_cfg->equals(my_cfg, other_cfg))
+			{
+				added->remove_at(added, others);
+				other_cfg->destroy(other_cfg);
+				found = TRUE;
+				break;
+			}
+		}
+		added->reset_enumerator(added, others);
+		if (!found)
+		{
+			this->child_cfgs->remove_at(this->child_cfgs, mine);
+			removed->insert_last(removed, my_cfg);
+		}
+	}
+	while (others->enumerate(others, &other_cfg))
+	{
+		this->child_cfgs->insert_last(this->child_cfgs,
+									  other_cfg->get_ref(other_cfg));
+	}
+	others->destroy(others);
+	mine->destroy(mine);
+	this->mutex->unlock(this->mutex);
+
+	INIT(enumerator,
+		.public = {
+			.enumerate = (void*)_child_cfgs_replace_enumerate,
+			.destroy = (void*)_child_cfgs_replace_enumerator_destroy,
+		},
+		.removed = removed,
+		.added = added,
+	);
+	return &enumerator->public;
+}
+
 /**
  * child_cfg enumerator
  */
@@ -538,10 +649,6 @@ static bool auth_cfg_equal(private_peer_cfg_t *this, private_peer_cfg_t *other)
 METHOD(peer_cfg_t, equals, bool,
 	private_peer_cfg_t *this, private_peer_cfg_t *other)
 {
-	enumerator_t *e1, *e2;
-	host_t *vip1, *vip2;
-	char *pool1, *pool2;
-
 	if (this == other)
 	{
 		return TRUE;
@@ -550,44 +657,15 @@ METHOD(peer_cfg_t, equals, bool,
 	{
 		return FALSE;
 	}
-
-	if (this->vips->get_count(this->vips) != other->vips->get_count(other->vips))
+	if (!this->vips->equals_offset(this->vips, other->vips,
+								   offsetof(host_t, ip_equals)))
 	{
 		return FALSE;
 	}
-	e1 = create_virtual_ip_enumerator(this);
-	e2 = create_virtual_ip_enumerator(other);
-	if (e1->enumerate(e1, &vip1) && e2->enumerate(e2, &vip2))
-	{
-		if (!vip1->ip_equals(vip1, vip2))
-		{
-			e1->destroy(e1);
-			e2->destroy(e2);
-			return FALSE;
-		}
-	}
-	e1->destroy(e1);
-	e2->destroy(e2);
-
-	if (this->pools->get_count(this->pools) !=
-		other->pools->get_count(other->pools))
+	if (!this->pools->equals_function(this->pools, other->pools, (void*)streq))
 	{
 		return FALSE;
 	}
-	e1 = create_pool_enumerator(this);
-	e2 = create_pool_enumerator(other);
-	if (e1->enumerate(e1, &pool1) && e2->enumerate(e2, &pool2))
-	{
-		if (!streq(pool1, pool2))
-		{
-			e1->destroy(e1);
-			e2->destroy(e2);
-			return FALSE;
-		}
-	}
-	e1->destroy(e1);
-	e2->destroy(e2);
-
 	return (
 		get_ike_version(this) == get_ike_version(other) &&
 		this->cert_policy == other->cert_policy &&
@@ -666,6 +744,10 @@ peer_cfg_t *peer_cfg_create(char *name,
 	{
 		jitter_time = reauth_time;
 	}
+	if (dpd && dpd_timeout && dpd > dpd_timeout)
+	{
+		dpd_timeout = dpd;
+	}
 
 	INIT(this,
 		.public = {
@@ -674,6 +756,7 @@ peer_cfg_t *peer_cfg_create(char *name,
 			.get_ike_cfg = _get_ike_cfg,
 			.add_child_cfg = _add_child_cfg,
 			.remove_child_cfg = (void*)_remove_child_cfg,
+			.replace_child_cfgs = _replace_child_cfgs,
 			.create_child_cfg_enumerator = _create_child_cfg_enumerator,
 			.select_child_cfg = _select_child_cfg,
 			.get_cert_policy = _get_cert_policy,
diff --git a/src/libcharon/config/peer_cfg.h b/src/libcharon/config/peer_cfg.h
index 3e78039..b612a2e 100644
--- a/src/libcharon/config/peer_cfg.h
+++ b/src/libcharon/config/peer_cfg.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2008 Tobias Brunner
+ * Copyright (C) 2007-2015 Tobias Brunner
  * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
@@ -154,6 +154,20 @@ struct peer_cfg_t {
 	void (*remove_child_cfg)(peer_cfg_t *this, enumerator_t *enumerator);
 
 	/**
+	 * Replace the CHILD configs with those in the given PEER config.
+	 *
+	 * Configs that are equal are not replaced.
+	 *
+	 * The enumerator enumerates the removed and added CHILD configs
+	 * (child_cfg_t*, bool), where the flag is FALSE for removed configs and
+	 * TRUE for added configs.
+	 *
+	 * @param other			other config to get CHILD configs from
+	 * @return				an enumerator over removed/added CHILD configs
+	 */
+	enumerator_t* (*replace_child_cfgs)(peer_cfg_t *this, peer_cfg_t *other);
+
+	/**
 	 * Create an enumerator for all attached CHILD configs.
 	 *
 	 * @return				an enumerator over all CHILD configs.
diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c
index e59dcd9..95b6a00 100644
--- a/src/libcharon/config/proposal.c
+++ b/src/libcharon/config/proposal.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2008-2014 Tobias Brunner
  * Copyright (C) 2006-2010 Martin Willi
+ * Copyright (C) 2013-2015 Andreas Steffen
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -640,20 +641,41 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
 
 	if (aead)
 	{
+		/* Round 1 adds algorithms with at least 128 bit security strength */
 		enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
 		while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
 		{
 			switch (encryption)
 			{
-				case ENCR_AES_CCM_ICV8:
-				case ENCR_AES_CCM_ICV12:
+				case ENCR_AES_GCM_ICV16:
 				case ENCR_AES_CCM_ICV16:
-				case ENCR_AES_GCM_ICV8:
+				case ENCR_CAMELLIA_CCM_ICV16:
+					/* we assume that we support all AES/Camellia sizes */
+					add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 128);
+					add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192);
+					add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256);
+					break;
+				case ENCR_CHACHA20_POLY1305:
+					add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256);
+					break;
+				default:
+					break;
+			}
+		}
+		enumerator->destroy(enumerator);
+
+		/* Round 2 adds algorithms with less than 128 bit security strength */
+		enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
+		while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
+		{
+			switch (encryption)
+			{
 				case ENCR_AES_GCM_ICV12:
-				case ENCR_AES_GCM_ICV16:
-				case ENCR_CAMELLIA_CCM_ICV8:
+				case ENCR_AES_GCM_ICV8:
+				case ENCR_AES_CCM_ICV12:
+				case ENCR_AES_CCM_ICV8:
 				case ENCR_CAMELLIA_CCM_ICV12:
-				case ENCR_CAMELLIA_CCM_ICV16:
+				case ENCR_CAMELLIA_CCM_ICV8:
 					/* we assume that we support all AES/Camellia sizes */
 					add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 128);
 					add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192);
@@ -672,6 +694,7 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
 	}
 	else
 	{
+		/* Round 1 adds algorithms with at least 128 bit security strength */
 		enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
 		while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
 		{
@@ -686,6 +709,18 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
 					add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192);
 					add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256);
 					break;
+				default:
+					break;
+			}
+		}
+		enumerator->destroy(enumerator);
+
+		/* Round 2 adds algorithms with less than 128 bit security strength */
+		enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
+		while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
+		{
+			switch (encryption)
+			{
 				case ENCR_3DES:
 					add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 0);
 					break;
@@ -703,18 +738,33 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
 			return FALSE;
 		}
 
+		/* Round 1 adds algorithms with at least 128 bit security strength */
 		enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
 		while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
 		{
 			switch (integrity)
 			{
-				case AUTH_HMAC_SHA1_96:
 				case AUTH_HMAC_SHA2_256_128:
 				case AUTH_HMAC_SHA2_384_192:
 				case AUTH_HMAC_SHA2_512_256:
-				case AUTH_HMAC_MD5_96:
+					add_algorithm(this, INTEGRITY_ALGORITHM, integrity, 0);
+					break;
+				default:
+					break;
+			}
+		}
+		enumerator->destroy(enumerator);
+
+		/* Round 2 adds algorithms with less than 128 bit security strength */
+		enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
+		while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
+		{
+			switch (integrity)
+			{
 				case AUTH_AES_XCBC_96:
 				case AUTH_AES_CMAC_96:
+				case AUTH_HMAC_SHA1_96:
+				case AUTH_HMAC_MD5_96:
 					add_algorithm(this, INTEGRITY_ALGORITHM, integrity, 0);
 					break;
 				default:
@@ -724,16 +774,15 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
 		enumerator->destroy(enumerator);
 	}
 
+	/* Round 1 adds algorithms with at least 128 bit security strength */
 	enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
 	while (enumerator->enumerate(enumerator, &prf, &plugin_name))
 	{
 		switch (prf)
 		{
-			case PRF_HMAC_SHA1:
 			case PRF_HMAC_SHA2_256:
 			case PRF_HMAC_SHA2_384:
 			case PRF_HMAC_SHA2_512:
-			case PRF_HMAC_MD5:
 			case PRF_AES128_XCBC:
 			case PRF_AES128_CMAC:
 				add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0);
@@ -744,6 +793,63 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
 	}
 	enumerator->destroy(enumerator);
 
+	/* Round 2 adds algorithms with less than 128 bit security strength */
+	enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
+	while (enumerator->enumerate(enumerator, &prf, &plugin_name))
+	{
+		switch (prf)
+		{
+			case PRF_HMAC_SHA1:
+			case PRF_HMAC_MD5:
+				add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0);
+				break;
+			default:
+				break;
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	/* Round 1 adds ECC and NTRU algorithms with at least 128 bit security strength */
+	enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
+	while (enumerator->enumerate(enumerator, &group, &plugin_name))
+	{
+		switch (group)
+		{
+			case ECP_256_BIT:
+			case ECP_384_BIT:
+			case ECP_521_BIT:
+			case ECP_256_BP:
+			case ECP_384_BP:
+			case ECP_512_BP:
+			case NTRU_128_BIT:
+			case NTRU_192_BIT:
+			case NTRU_256_BIT:
+				add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0);
+				break;
+			default:
+				break;
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	/* Round 2 adds other algorithms with at least 128 bit security strength */
+	enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
+	while (enumerator->enumerate(enumerator, &group, &plugin_name))
+	{
+		switch (group)
+		{
+			case MODP_3072_BIT:
+			case MODP_4096_BIT:
+			case MODP_8192_BIT:
+				add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0);
+				break;
+			default:
+				break;
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	/* Round 3 adds algorithms with less than 128 bit security strength */
 	enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
 	while (enumerator->enumerate(enumerator, &group, &plugin_name))
 	{
@@ -755,28 +861,16 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
 			case MODP_768_BIT:
 				/* weak */
 				break;
-			case MODP_1024_BIT:
-			case MODP_1536_BIT:
 			case MODP_2048_BIT:
-			case MODP_3072_BIT:
-			case MODP_4096_BIT:
-			case MODP_8192_BIT:
-			case ECP_256_BIT:
-			case ECP_384_BIT:
-			case ECP_521_BIT:
-			case MODP_1024_160:
-			case MODP_2048_224:
 			case MODP_2048_256:
-			case ECP_192_BIT:
+			case MODP_2048_224:
+			case MODP_1536_BIT:
+			case MODP_1024_BIT:
+			case MODP_1024_160:
 			case ECP_224_BIT:
 			case ECP_224_BP:
-			case ECP_256_BP:
-			case ECP_384_BP:
-			case ECP_512_BP:
+			case ECP_192_BIT:
 			case NTRU_112_BIT:
-			case NTRU_128_BIT:
-			case NTRU_192_BIT:
-			case NTRU_256_BIT:
 				add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0);
 				break;
 			default:
@@ -805,21 +899,27 @@ proposal_t *proposal_create_default(protocol_id_t protocol)
 			}
 			break;
 		case PROTO_ESP:
-			add_algorithm(this, ENCRYPTION_ALGORITHM,   ENCR_AES_CBC,         128);
-			add_algorithm(this, ENCRYPTION_ALGORITHM,   ENCR_AES_CBC,         192);
-			add_algorithm(this, ENCRYPTION_ALGORITHM,   ENCR_AES_CBC,         256);
-			add_algorithm(this, ENCRYPTION_ALGORITHM,   ENCR_3DES,              0);
-			add_algorithm(this, ENCRYPTION_ALGORITHM,   ENCR_BLOWFISH,        256);
-			add_algorithm(this, INTEGRITY_ALGORITHM,    AUTH_HMAC_SHA1_96,      0);
-			add_algorithm(this, INTEGRITY_ALGORITHM,    AUTH_AES_XCBC_96,       0);
-			add_algorithm(this, INTEGRITY_ALGORITHM,    AUTH_HMAC_MD5_96,       0);
-			add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS,  0);
+			add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC,          128);
+			add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC,          192);
+			add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC,          256);
+			add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES,               0);
+			add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH,         256);
+			add_algorithm(this, INTEGRITY_ALGORITHM,  AUTH_HMAC_SHA2_256_128,  0);
+			add_algorithm(this, INTEGRITY_ALGORITHM,  AUTH_HMAC_SHA2_384_192,  0);
+			add_algorithm(this, INTEGRITY_ALGORITHM,  AUTH_HMAC_SHA2_512_256,  0);
+			add_algorithm(this, INTEGRITY_ALGORITHM,  AUTH_HMAC_SHA1_96,       0);
+			add_algorithm(this, INTEGRITY_ALGORITHM,  AUTH_AES_XCBC_96,        0);
+			add_algorithm(this, INTEGRITY_ALGORITHM,  AUTH_HMAC_MD5_96,        0);
+			add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
 			break;
 		case PROTO_AH:
-			add_algorithm(this, INTEGRITY_ALGORITHM,    AUTH_HMAC_SHA1_96,      0);
-			add_algorithm(this, INTEGRITY_ALGORITHM,    AUTH_AES_XCBC_96,       0);
-			add_algorithm(this, INTEGRITY_ALGORITHM,    AUTH_HMAC_MD5_96,       0);
-			add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS,  0);
+			add_algorithm(this, INTEGRITY_ALGORITHM,  AUTH_HMAC_SHA2_256_128,  0);
+			add_algorithm(this, INTEGRITY_ALGORITHM,  AUTH_HMAC_SHA2_384_192,  0);
+			add_algorithm(this, INTEGRITY_ALGORITHM,  AUTH_HMAC_SHA2_512_256,  0);
+			add_algorithm(this, INTEGRITY_ALGORITHM,  AUTH_HMAC_SHA1_96,       0);
+			add_algorithm(this, INTEGRITY_ALGORITHM,  AUTH_AES_XCBC_96,        0);
+			add_algorithm(this, INTEGRITY_ALGORITHM,  AUTH_HMAC_MD5_96,        0);
+			add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
 			break;
 		default:
 			break;
diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c
index dce2a71..cef8b89 100644
--- a/src/libcharon/daemon.c
+++ b/src/libcharon/daemon.c
@@ -16,6 +16,29 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2016 secunet Security Networks AG
+ * Copyright (C) 2016 Thomas Egerer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -111,6 +134,70 @@ static void dbg_bus(debug_t group, level_t level, char *fmt, ...)
 }
 
 /**
+ * Data for registered custom loggers
+ */
+typedef struct {
+	/**
+	 * Name of the custom logger (also used for loglevel configuration)
+	 */
+	char *name;
+
+	/**
+	 * Constructor to be called for custom logger creation
+	 */
+	custom_logger_constructor_t constructor;
+
+} custom_logger_entry_t;
+
+#define MAX_CUSTOM_LOGGERS 10
+
+/**
+ * Static array for logger registration using __attribute__((constructor))
+ */
+static custom_logger_entry_t custom_loggers[MAX_CUSTOM_LOGGERS];
+static int custom_logger_count;
+
+/**
+ * Described in header
+ */
+void register_custom_logger(char *name,
+							custom_logger_constructor_t constructor)
+{
+	if (custom_logger_count < MAX_CUSTOM_LOGGERS - 1)
+	{
+		custom_loggers[custom_logger_count].name = name;
+		custom_loggers[custom_logger_count].constructor = constructor;
+		custom_logger_count++;
+	}
+	else
+	{
+		fprintf(stderr, "failed to register custom logger, please increase "
+				"MAX_CUSTOM_LOGGERS");
+	}
+}
+
+/**
+ * Types of supported loggers
+ */
+typedef enum {
+	/**
+	 * Syslog logger instance
+	 */
+	SYS_LOGGER,
+
+	/**
+	 * File logger instance
+	 */
+	FILE_LOGGER,
+
+	/**
+	 * Custom logger instance
+	 */
+	CUSTOM_LOGGER,
+
+} logger_type_t;
+
+/**
  * Some metadata about configured loggers
  */
 typedef struct {
@@ -120,9 +207,9 @@ typedef struct {
 	char *target;
 
 	/**
-	 * TRUE if this is a file logger
+	 * Type of logger
 	 */
-	bool file;
+	logger_type_t type;
 
 	/**
 	 * The actual logger
@@ -130,6 +217,7 @@ typedef struct {
 	union {
 		sys_logger_t *sys;
 		file_logger_t *file;
+		custom_logger_t *custom;
 	} logger;
 
 } logger_entry_t;
@@ -139,13 +227,17 @@ typedef struct {
  */
 static void logger_entry_destroy(logger_entry_t *this)
 {
-	if (this->file)
-	{
-		DESTROY_IF(this->logger.file);
-	}
-	else
+	switch (this->type)
 	{
-		DESTROY_IF(this->logger.sys);
+		case FILE_LOGGER:
+			DESTROY_IF(this->logger.file);
+			break;
+		case SYS_LOGGER:
+			DESTROY_IF(this->logger.sys);
+			break;
+		case CUSTOM_LOGGER:
+			DESTROY_IF(this->logger.custom);
+			break;
 	}
 	free(this->target);
 	free(this);
@@ -156,13 +248,18 @@ static void logger_entry_destroy(logger_entry_t *this)
  */
 static void logger_entry_unregister_destroy(logger_entry_t *this)
 {
-	if (this->file)
+	switch (this->type)
 	{
-		charon->bus->remove_logger(charon->bus, &this->logger.file->logger);
-	}
-	else
-	{
-		charon->bus->remove_logger(charon->bus, &this->logger.sys->logger);
+		case FILE_LOGGER:
+			charon->bus->remove_logger(charon->bus, &this->logger.file->logger);
+			break;
+		case SYS_LOGGER:
+			charon->bus->remove_logger(charon->bus, &this->logger.sys->logger);
+			break;
+		case CUSTOM_LOGGER:
+			charon->bus->remove_logger(charon->bus,
+									   &this->logger.custom->logger);
+			break;
 	}
 	logger_entry_destroy(this);
 }
@@ -170,9 +267,10 @@ static void logger_entry_unregister_destroy(logger_entry_t *this)
 /**
  * Match a logger entry by target and whether it is a file or syslog logger
  */
-static bool logger_entry_match(logger_entry_t *this, char *target, bool *file)
+static bool logger_entry_match(logger_entry_t *this, char *target,
+							   logger_type_t *type)
 {
-	return this->file == *file && streq(this->target, target);
+	return this->type == *type && streq(this->target, target);
 }
 
 /**
@@ -228,28 +326,45 @@ static int get_syslog_facility(char *facility)
  * Returns an existing or newly created logger entry (if found, it is removed
  * from the given linked list of existing loggers)
  */
-static logger_entry_t *get_logger_entry(char *target, bool is_file_logger,
-										linked_list_t *existing)
+static logger_entry_t *get_logger_entry(char *target, logger_type_t type,
+										linked_list_t *existing,
+										custom_logger_constructor_t constructor)
 {
 	logger_entry_t *entry;
 
 	if (existing->find_first(existing, (void*)logger_entry_match,
-							(void**)&entry, target, &is_file_logger) != SUCCESS)
+							(void**)&entry, target, &type) != SUCCESS)
 	{
 		INIT(entry,
 			.target = strdup(target),
-			.file = is_file_logger,
+			.type = type,
 		);
-		if (is_file_logger)
+		switch (type)
 		{
-			entry->logger.file = file_logger_create(target);
-		}
+			case FILE_LOGGER:
+				entry->logger.file = file_logger_create(target);
+				break;
+			case SYS_LOGGER:
 #ifdef HAVE_SYSLOG
-		else
-		{
-			entry->logger.sys = sys_logger_create(get_syslog_facility(target));
-		}
+				entry->logger.sys = sys_logger_create(
+												get_syslog_facility(target));
+				break;
+#else
+				free(entry);
+				return NULL;
 #endif /* HAVE_SYSLOG */
+			case CUSTOM_LOGGER:
+				if (constructor)
+				{
+					entry->logger.custom = constructor(target);
+				}
+				if (!entry->logger.custom)
+				{
+					free(entry);
+					return NULL;
+				}
+				break;
+		}
 	}
 	else
 	{
@@ -266,9 +381,12 @@ static sys_logger_t *add_sys_logger(private_daemon_t *this, char *facility,
 {
 	logger_entry_t *entry;
 
-	entry = get_logger_entry(facility, FALSE, current_loggers);
-	this->loggers->insert_last(this->loggers, entry);
-	return entry->logger.sys;
+	entry = get_logger_entry(facility, SYS_LOGGER, current_loggers, NULL);
+	if (entry)
+	{
+		this->loggers->insert_last(this->loggers, entry);
+	}
+	return entry ? entry->logger.sys : NULL;
 }
 
 /**
@@ -279,9 +397,30 @@ static file_logger_t *add_file_logger(private_daemon_t *this, char *filename,
 {
 	logger_entry_t *entry;
 
-	entry = get_logger_entry(filename, TRUE, current_loggers);
-	this->loggers->insert_last(this->loggers, entry);
-	return entry->logger.file;
+	entry = get_logger_entry(filename, FILE_LOGGER, current_loggers, NULL);
+	if (entry)
+	{
+		this->loggers->insert_last(this->loggers, entry);
+	}
+	return entry ? entry->logger.file : NULL;
+}
+
+ /**
+ * Create or reuse a custom logger
+ */
+static custom_logger_t *add_custom_logger(private_daemon_t *this,
+										  custom_logger_entry_t *custom,
+										  linked_list_t *current_loggers)
+{
+	logger_entry_t *entry;
+
+	entry = get_logger_entry(custom->name, CUSTOM_LOGGER, current_loggers,
+							 custom->constructor);
+	if (entry)
+	{
+		this->loggers->insert_last(this->loggers, entry);
+	}
+	return entry ? entry->logger.custom : NULL;
 }
 
 /**
@@ -300,6 +439,11 @@ static void load_sys_logger(private_daemon_t *this, char *facility,
 	}
 
 	sys_logger = add_sys_logger(this, facility, current_loggers);
+	if (!sys_logger)
+	{
+		return;
+	}
+
 	sys_logger->set_options(sys_logger,
 				lib->settings->get_bool(lib->settings, "%s.syslog.%s.ike_name",
 										FALSE, lib->ns, facility));
@@ -339,6 +483,11 @@ static void load_file_logger(private_daemon_t *this, char *filename,
 						"%s.filelog.%s.append", TRUE, lib->ns, filename);
 
 	file_logger = add_file_logger(this, filename, current_loggers);
+	if (!file_logger)
+	{
+		return;
+	}
+
 	file_logger->set_options(file_logger, time_format, add_ms, ike_name);
 	file_logger->open(file_logger, flush_line, append);
 
@@ -353,12 +502,41 @@ static void load_file_logger(private_daemon_t *this, char *filename,
 	charon->bus->add_logger(charon->bus, &file_logger->logger);
 }
 
+/**
+ * Load the given custom logger configured in strongswan.conf
+ */
+static void load_custom_logger(private_daemon_t *this,
+							   custom_logger_entry_t *entry,
+							   linked_list_t *current_loggers)
+{
+	custom_logger_t *custom_logger;
+	debug_t group;
+	level_t def;
+
+	custom_logger = add_custom_logger(this, entry, current_loggers);
+	if (!custom_logger)
+	{
+		return;
+	}
+
+	def = lib->settings->get_int(lib->settings, "%s.customlog.%s.default", 1,
+								 lib->ns, entry->name);
+	for (group = 0; group < DBG_MAX; group++)
+	{
+		custom_logger->set_level(custom_logger, group,
+				lib->settings->get_int(lib->settings, "%s.customlog.%s.%N", def,
+							lib->ns, entry->name, debug_lower_names, group));
+	}
+	charon->bus->add_logger(charon->bus, &custom_logger->logger);
+}
+
 METHOD(daemon_t, load_loggers, void,
 	private_daemon_t *this, level_t levels[DBG_MAX], bool to_stderr)
 {
 	enumerator_t *enumerator;
 	linked_list_t *current_loggers;
 	char *target;
+	int i;
 
 	this->mutex->lock(this->mutex);
 	handle_syslog_identifier(this);
@@ -380,6 +558,11 @@ METHOD(daemon_t, load_loggers, void,
 	}
 	enumerator->destroy(enumerator);
 
+	for (i = 0; i < custom_logger_count; ++i)
+	{
+		load_custom_logger(this, &custom_loggers[i], current_loggers);
+	}
+
 	if (!this->loggers->get_count(this->loggers) && levels)
 	{	/* setup legacy style default loggers configured via command-line */
 		file_logger_t *file_logger;
@@ -431,15 +614,24 @@ METHOD(daemon_t, set_level, void,
 	enumerator = this->loggers->create_enumerator(this->loggers);
 	while (enumerator->enumerate(enumerator, &entry))
 	{
-		if (entry->file)
-		{
-			entry->logger.file->set_level(entry->logger.file, group, level);
-			charon->bus->add_logger(charon->bus, &entry->logger.file->logger);
-		}
-		else
+		switch (entry->type)
 		{
-			entry->logger.sys->set_level(entry->logger.sys, group, level);
-			charon->bus->add_logger(charon->bus, &entry->logger.sys->logger);
+			case FILE_LOGGER:
+				entry->logger.file->set_level(entry->logger.file, group, level);
+				charon->bus->add_logger(charon->bus,
+										&entry->logger.file->logger);
+				break;
+			case SYS_LOGGER:
+				entry->logger.sys->set_level(entry->logger.sys, group, level);
+				charon->bus->add_logger(charon->bus,
+										&entry->logger.sys->logger);
+				break;
+			case CUSTOM_LOGGER:
+				entry->logger.custom->set_level(entry->logger.custom, group,
+												level);
+				charon->bus->add_logger(charon->bus,
+										&entry->logger.sys->logger);
+				break;
 		}
 	}
 	enumerator->destroy(enumerator);
@@ -488,11 +680,13 @@ static void destroy(private_daemon_t *this)
 	DESTROY_IF(this->kernel_handler);
 	DESTROY_IF(this->public.traps);
 	DESTROY_IF(this->public.shunts);
+	DESTROY_IF(this->public.redirect);
 	DESTROY_IF(this->public.controller);
 	DESTROY_IF(this->public.eap);
 	DESTROY_IF(this->public.xauth);
 	DESTROY_IF(this->public.backends);
 	DESTROY_IF(this->public.socket);
+	DESTROY_IF(this->public.kernel);
 
 	/* rehook library logging, shutdown logging */
 	dbg = dbg_old;
@@ -670,6 +864,7 @@ private_daemon_t *daemon_create()
 		.ref = 1,
 	);
 	charon = &this->public;
+	this->public.kernel = kernel_interface_create();
 	this->public.attributes = attribute_manager_create();
 	this->public.controller = controller_create();
 	this->public.eap = eap_manager_create();
@@ -678,6 +873,7 @@ private_daemon_t *daemon_create()
 	this->public.socket = socket_manager_create();
 	this->public.traps = trap_manager_create();
 	this->public.shunts = shunt_manager_create();
+	this->public.redirect = redirect_manager_create();
 	this->kernel_handler = kernel_handler_create();
 
 	return this;
diff --git a/src/libcharon/daemon.h b/src/libcharon/daemon.h
index d16bf1d..48b9c7e 100644
--- a/src/libcharon/daemon.h
+++ b/src/libcharon/daemon.h
@@ -16,6 +16,29 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2016 secunet Security Networks AG
+ * Copyright (C) 2016 Thomas Egerer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 /**
  * @defgroup libcharon libcharon
  *
@@ -40,7 +63,7 @@
  * @defgroup payloads payloads
  * @ingroup encoding
  *
- * @defgroup ckernel kernel
+ * @defgroup kernel kernel
  * @ingroup libcharon
  *
  * @defgroup network network
@@ -156,15 +179,18 @@
 typedef struct daemon_t daemon_t;
 
 #include <attributes/attribute_manager.h>
+#include <kernel/kernel_interface.h>
 #include <network/sender.h>
 #include <network/receiver.h>
 #include <network/socket_manager.h>
 #include <control/controller.h>
 #include <bus/bus.h>
+#include <bus/listeners/custom_logger.h>
 #include <sa/ike_sa_manager.h>
 #include <sa/child_sa_manager.h>
 #include <sa/trap_manager.h>
 #include <sa/shunt_manager.h>
+#include <sa/redirect_manager.h>
 #include <config/backend_manager.h>
 #include <sa/eap/eap_manager.h>
 #include <sa/xauth/xauth_manager.h>
@@ -215,6 +241,11 @@ struct daemon_t {
 	socket_manager_t *socket;
 
 	/**
+	 * Kernel interface to communicate with kernel
+	 */
+	kernel_interface_t *kernel;
+
+	/**
 	 * A ike_sa_manager_t instance.
 	 */
 	ike_sa_manager_t *ike_sa_manager;
@@ -235,6 +266,11 @@ struct daemon_t {
 	shunt_manager_t *shunts;
 
 	/**
+	 * Manager for IKE redirect providers
+	 */
+	redirect_manager_t *redirect;
+
+	/**
 	 * Manager for the different configuration backends.
 	 */
 	backend_manager_t *backends;
@@ -311,8 +347,8 @@ struct daemon_t {
 						 bool to_stderr);
 
 	/**
-	 * Set the log level for the given log group for all configured file- and
-	 * syslog-loggers.
+	 * Set the log level for the given log group for all configured file-,
+	 * syslog and custom-loggers.
 	 *
 	 * @param group		log group
 	 * @param level		log level
@@ -345,4 +381,15 @@ bool libcharon_init();
  */
 void libcharon_deinit();
 
+/**
+ * Register a custom logger constructor.
+ *
+ * To be called from __attribute__((constructor)) functions.
+ *
+ * @param name				name of the logger (also used for loglevel config)
+ * @param constructor		constructor to create custom logger
+ */
+void register_custom_logger(char *name,
+							custom_logger_constructor_t constructor);
+
 #endif /** DAEMON_H_ @}*/
diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c
index 3303024..bbdc462 100644
--- a/src/libcharon/encoding/message.c
+++ b/src/libcharon/encoding/message.c
@@ -551,13 +551,13 @@ static payload_order_t aggressive_i_order[] = {
 	{PLV1_NONCE,					0},
 	{PLV1_ID,						0},
 	{PLV1_CERTIFICATE,				0},
+	{PLV1_CERTREQ,					0},
+	{PLV1_NOTIFY,					0},
+	{PLV1_VENDOR_ID,				0},
 	{PLV1_NAT_D,					0},
 	{PLV1_NAT_D_DRAFT_00_03,		0},
 	{PLV1_SIGNATURE,				0},
 	{PLV1_HASH,						0},
-	{PLV1_CERTREQ,					0},
-	{PLV1_NOTIFY,					0},
-	{PLV1_VENDOR_ID,				0},
 	{PLV1_FRAGMENT,					0},
 };
 
@@ -591,13 +591,13 @@ static payload_order_t aggressive_r_order[] = {
 	{PLV1_NONCE,					0},
 	{PLV1_ID,						0},
 	{PLV1_CERTIFICATE,				0},
+	{PLV1_CERTREQ,					0},
+	{PLV1_NOTIFY,					0},
+	{PLV1_VENDOR_ID,				0},
 	{PLV1_NAT_D,					0},
 	{PLV1_NAT_D_DRAFT_00_03,		0},
 	{PLV1_SIGNATURE,				0},
 	{PLV1_HASH,						0},
-	{PLV1_CERTREQ,					0},
-	{PLV1_NOTIFY,					0},
-	{PLV1_VENDOR_ID,				0},
 	{PLV1_FRAGMENT,					0},
 };
 
diff --git a/src/libcharon/encoding/payloads/configuration_attribute.c b/src/libcharon/encoding/payloads/configuration_attribute.c
index 481bb7b..4ecdf56 100644
--- a/src/libcharon/encoding/payloads/configuration_attribute.c
+++ b/src/libcharon/encoding/payloads/configuration_attribute.c
@@ -132,6 +132,7 @@ METHOD(payload_t, verify, status_t,
 		case INTERNAL_IP4_NBNS:
 		case INTERNAL_ADDRESS_EXPIRY:
 		case INTERNAL_IP4_DHCP:
+		case P_CSCF_IP4_ADDRESS:
 			if (this->length_or_value != 0 && this->length_or_value != 4)
 			{
 				failed = TRUE;
@@ -144,6 +145,13 @@ METHOD(payload_t, verify, status_t,
 			}
 			break;
 		case INTERNAL_IP6_ADDRESS:
+			if (this->type == PLV1_CONFIGURATION_ATTRIBUTE &&
+				this->length_or_value == 16)
+			{	/* 16 bytes are correct for IKEv1, but older releases sent a
+				 * prefix byte so we still accept 0 or 17 as in IKEv2 */
+				break;
+			}
+			/* fall-through */
 		case INTERNAL_IP6_SUBNET:
 			if (this->length_or_value != 0 && this->length_or_value != 17)
 			{
@@ -153,6 +161,7 @@ METHOD(payload_t, verify, status_t,
 		case INTERNAL_IP6_DNS:
 		case INTERNAL_IP6_NBNS:
 		case INTERNAL_IP6_DHCP:
+		case P_CSCF_IP6_ADDRESS:
 			if (this->length_or_value != 0 && this->length_or_value != 16)
 			{
 				failed = TRUE;
diff --git a/src/libcharon/kernel/kernel_handler.c b/src/libcharon/kernel/kernel_handler.c
index 9c0e260..be37d30 100644
--- a/src/libcharon/kernel/kernel_handler.c
+++ b/src/libcharon/kernel/kernel_handler.c
@@ -15,7 +15,6 @@
 
 #include "kernel_handler.h"
 
-#include <hydra.h>
 #include <daemon.h>
 #include <processing/jobs/acquire_job.h>
 #include <processing/jobs/delete_child_sa_job.h>
@@ -135,8 +134,7 @@ METHOD(kernel_listener_t, roam, bool,
 METHOD(kernel_handler_t, destroy, void,
 	private_kernel_handler_t *this)
 {
-	hydra->kernel_interface->remove_listener(hydra->kernel_interface,
-											 &this->public.listener);
+	charon->kernel->remove_listener(charon->kernel, &this->public.listener);
 	free(this);
 }
 
@@ -157,8 +155,7 @@ kernel_handler_t *kernel_handler_create()
 		},
 	);
 
-	hydra->kernel_interface->add_listener(hydra->kernel_interface,
-										  &this->public.listener);
+	charon->kernel->add_listener(charon->kernel, &this->public.listener);
 
 	return &this->public;
 }
diff --git a/src/libcharon/kernel/kernel_handler.h b/src/libcharon/kernel/kernel_handler.h
index 48ad688..f1fa0bd 100644
--- a/src/libcharon/kernel/kernel_handler.h
+++ b/src/libcharon/kernel/kernel_handler.h
@@ -15,7 +15,7 @@
 
 /**
  * @defgroup kernel_handler kernel_handler
- * @{ @ingroup ckernel
+ * @{ @ingroup kernel
  */
 
 #ifndef KERNEL_HANDLER_H_
diff --git a/src/libcharon/kernel/kernel_interface.c b/src/libcharon/kernel/kernel_interface.c
new file mode 100644
index 0000000..40c4ee5
--- /dev/null
+++ b/src/libcharon/kernel/kernel_interface.c
@@ -0,0 +1,1085 @@
+/*
+ * Copyright (C) 2008-2015 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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.
+ */
+
+/*
+ * Copyright (c) 2012 Nanoteq Pty Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "kernel_interface.h"
+
+#include <utils/debug.h>
+#include <threading/mutex.h>
+#include <collections/linked_list.h>
+#include <collections/hashtable.h>
+#include <collections/array.h>
+
+typedef struct private_kernel_interface_t private_kernel_interface_t;
+
+typedef struct kernel_algorithm_t kernel_algorithm_t;
+
+/**
+ * Mapping of IKE algorithms to kernel-specific algorithm identifiers
+ */
+struct kernel_algorithm_t {
+
+	/**
+	 * Transform type of the algorithm
+	 */
+	transform_type_t type;
+
+	/**
+	 * Identifier specified in IKE
+	 */
+	u_int16_t ike;
+
+	/**
+	 * Identifier as defined in pfkeyv2.h
+	 */
+	u_int16_t kernel;
+
+	/**
+	 * Name of the algorithm in linux crypto API
+	 */
+	char *name;
+};
+
+/**
+ * Private data of a kernel_interface_t object.
+ */
+struct private_kernel_interface_t {
+
+	/**
+	 * Public part of kernel_interface_t object.
+	 */
+	kernel_interface_t public;
+
+	/**
+	 * Registered IPsec constructor
+	 */
+	kernel_ipsec_constructor_t ipsec_constructor;
+
+	/**
+	 * Registered net constructor
+	 */
+	kernel_net_constructor_t net_constructor;
+
+	/**
+	 * ipsec interface
+	 */
+	kernel_ipsec_t *ipsec;
+
+	/**
+	 * network interface
+	 */
+	kernel_net_t *net;
+
+	/**
+	 * mutex for listeners
+	 */
+	mutex_t *mutex;
+
+	/**
+	 * list of registered listeners
+	 */
+	linked_list_t *listeners;
+
+	/**
+	 * Reqid entries indexed by reqids
+	 */
+	hashtable_t *reqids;
+
+	/**
+	 * Reqid entries indexed by traffic selectors
+	 */
+	hashtable_t *reqids_by_ts;
+
+	/**
+	 * mutex for algorithm mappings
+	 */
+	mutex_t *mutex_algs;
+
+	/**
+	 * List of algorithm mappings (kernel_algorithm_t*)
+	 */
+	linked_list_t *algorithms;
+
+	/**
+	 * List of interface names to include or exclude (char*), NULL if interfaces
+	 * are not filtered
+	 */
+	linked_list_t *ifaces_filter;
+
+	/**
+	 * TRUE to exclude interfaces listed in ifaces_filter, FALSE to consider
+	 * only those listed there
+	 */
+	bool ifaces_exclude;
+};
+
+METHOD(kernel_interface_t, get_features, kernel_feature_t,
+	private_kernel_interface_t *this)
+{
+	kernel_feature_t features = 0;
+
+	if (this->ipsec && this->ipsec->get_features)
+	{
+		features |= this->ipsec->get_features(this->ipsec);
+	}
+	if (this->net && this->net->get_features)
+	{
+		features |= this->net->get_features(this->net);
+	}
+	return features;
+}
+
+METHOD(kernel_interface_t, get_spi, status_t,
+	private_kernel_interface_t *this, host_t *src, host_t *dst,
+	u_int8_t protocol, u_int32_t *spi)
+{
+	if (!this->ipsec)
+	{
+		return NOT_SUPPORTED;
+	}
+	return this->ipsec->get_spi(this->ipsec, src, dst, protocol, spi);
+}
+
+METHOD(kernel_interface_t, get_cpi, status_t,
+	private_kernel_interface_t *this, host_t *src, host_t *dst,
+	u_int16_t *cpi)
+{
+	if (!this->ipsec)
+	{
+		return NOT_SUPPORTED;
+	}
+	return this->ipsec->get_cpi(this->ipsec, src, dst, cpi);
+}
+
+/**
+ * Reqid mapping entry
+ */
+typedef struct {
+	/** allocated reqid */
+	u_int32_t reqid;
+	/** references to this entry */
+	u_int refs;
+	/** inbound mark used for SA */
+	mark_t mark_in;
+	/** outbound mark used for SA */
+	mark_t mark_out;
+	/** local traffic selectors */
+	array_t *local;
+	/** remote traffic selectors */
+	array_t *remote;
+} reqid_entry_t;
+
+/**
+ * Destroy a reqid mapping entry
+ */
+static void reqid_entry_destroy(reqid_entry_t *entry)
+{
+	array_destroy_offset(entry->local, offsetof(traffic_selector_t, destroy));
+	array_destroy_offset(entry->remote, offsetof(traffic_selector_t, destroy));
+	free(entry);
+}
+
+/**
+ * Hashtable hash function for reqid entries using reqid as key
+ */
+static u_int hash_reqid(reqid_entry_t *entry)
+{
+	return chunk_hash_inc(chunk_from_thing(entry->reqid),
+				chunk_hash_inc(chunk_from_thing(entry->mark_in),
+					chunk_hash(chunk_from_thing(entry->mark_out))));
+}
+
+/**
+ * Hashtable equals function for reqid entries using reqid as key
+ */
+static bool equals_reqid(reqid_entry_t *a, reqid_entry_t *b)
+{
+	return a->reqid == b->reqid &&
+		   a->mark_in.value == b->mark_in.value &&
+		   a->mark_in.mask == b->mark_in.mask &&
+		   a->mark_out.value == b->mark_out.value &&
+		   a->mark_out.mask == b->mark_out.mask;
+}
+
+/**
+ * Hash an array of traffic selectors
+ */
+static u_int hash_ts_array(array_t *array, u_int hash)
+{
+	enumerator_t *enumerator;
+	traffic_selector_t *ts;
+
+	enumerator = array_create_enumerator(array);
+	while (enumerator->enumerate(enumerator, &ts))
+	{
+		hash = ts->hash(ts, hash);
+	}
+	enumerator->destroy(enumerator);
+
+	return hash;
+}
+
+/**
+ * Hashtable hash function for reqid entries using traffic selectors as key
+ */
+static u_int hash_reqid_by_ts(reqid_entry_t *entry)
+{
+	return hash_ts_array(entry->local, hash_ts_array(entry->remote,
+			chunk_hash_inc(chunk_from_thing(entry->mark_in),
+				chunk_hash(chunk_from_thing(entry->mark_out)))));
+}
+
+/**
+ * Compare two array with traffic selectors for equality
+ */
+static bool ts_array_equals(array_t *a, array_t *b)
+{
+	traffic_selector_t *tsa, *tsb;
+	enumerator_t *ae, *be;
+	bool equal = TRUE;
+
+	if (array_count(a) != array_count(b))
+	{
+		return FALSE;
+	}
+
+	ae = array_create_enumerator(a);
+	be = array_create_enumerator(b);
+	while (equal && ae->enumerate(ae, &tsa) && be->enumerate(be, &tsb))
+	{
+		equal = tsa->equals(tsa, tsb);
+	}
+	ae->destroy(ae);
+	be->destroy(be);
+
+	return equal;
+}
+
+/**
+ * Hashtable equals function for reqid entries using traffic selectors as key
+ */
+static bool equals_reqid_by_ts(reqid_entry_t *a, reqid_entry_t *b)
+{
+	return ts_array_equals(a->local, b->local) &&
+		   ts_array_equals(a->remote, b->remote) &&
+		   a->mark_in.value == b->mark_in.value &&
+		   a->mark_in.mask == b->mark_in.mask &&
+		   a->mark_out.value == b->mark_out.value &&
+		   a->mark_out.mask == b->mark_out.mask;
+}
+
+/**
+ * Create an array from copied traffic selector list items
+ */
+static array_t *array_from_ts_list(linked_list_t *list)
+{
+	enumerator_t *enumerator;
+	traffic_selector_t *ts;
+	array_t *array;
+
+	array = array_create(0, 0);
+
+	enumerator = list->create_enumerator(list);
+	while (enumerator->enumerate(enumerator, &ts))
+	{
+		array_insert(array, ARRAY_TAIL, ts->clone(ts));
+	}
+	enumerator->destroy(enumerator);
+
+	return array;
+}
+
+METHOD(kernel_interface_t, alloc_reqid, status_t,
+	private_kernel_interface_t *this,
+	linked_list_t *local_ts, linked_list_t *remote_ts,
+	mark_t mark_in, mark_t mark_out, u_int32_t *reqid)
+{
+	static u_int32_t counter = 0;
+	reqid_entry_t *entry = NULL, *tmpl;
+	status_t status = SUCCESS;
+
+	INIT(tmpl,
+		.local = array_from_ts_list(local_ts),
+		.remote = array_from_ts_list(remote_ts),
+		.mark_in = mark_in,
+		.mark_out = mark_out,
+		.reqid = *reqid,
+	);
+
+	this->mutex->lock(this->mutex);
+	if (tmpl->reqid)
+	{
+		/* search by reqid if given */
+		entry = this->reqids->get(this->reqids, tmpl);
+	}
+	if (entry)
+	{
+		/* we don't require a traffic selector match for explicit reqids,
+		 * as we wan't to reuse a reqid for trap-triggered policies that
+		 * got narrowed during negotiation. */
+		reqid_entry_destroy(tmpl);
+	}
+	else
+	{
+		/* search by traffic selectors */
+		entry = this->reqids_by_ts->get(this->reqids_by_ts, tmpl);
+		if (entry)
+		{
+			reqid_entry_destroy(tmpl);
+		}
+		else
+		{
+			/* none found, create a new entry, allocating a reqid */
+			entry = tmpl;
+			entry->reqid = ++counter;
+			this->reqids_by_ts->put(this->reqids_by_ts, entry, entry);
+			this->reqids->put(this->reqids, entry, entry);
+		}
+		*reqid = entry->reqid;
+	}
+	entry->refs++;
+	this->mutex->unlock(this->mutex);
+
+	return status;
+}
+
+METHOD(kernel_interface_t, release_reqid, status_t,
+	private_kernel_interface_t *this, u_int32_t reqid,
+	mark_t mark_in, mark_t mark_out)
+{
+	reqid_entry_t *entry, tmpl = {
+		.reqid = reqid,
+		.mark_in = mark_in,
+		.mark_out = mark_out,
+	};
+
+	this->mutex->lock(this->mutex);
+	entry = this->reqids->remove(this->reqids, &tmpl);
+	if (entry)
+	{
+		if (--entry->refs == 0)
+		{
+			entry = this->reqids_by_ts->remove(this->reqids_by_ts, entry);
+			if (entry)
+			{
+				reqid_entry_destroy(entry);
+			}
+		}
+		else
+		{
+			this->reqids->put(this->reqids, entry, entry);
+		}
+	}
+	this->mutex->unlock(this->mutex);
+
+	if (entry)
+	{
+		return SUCCESS;
+	}
+	return NOT_FOUND;
+}
+
+METHOD(kernel_interface_t, add_sa, status_t,
+	private_kernel_interface_t *this, host_t *src, host_t *dst,
+	u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
+	u_int32_t tfc, lifetime_cfg_t *lifetime, 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, u_int32_t replay_window,
+	bool initiator, bool encap, bool esn, bool inbound, bool update,
+	linked_list_t *src_ts, linked_list_t *dst_ts)
+{
+	if (!this->ipsec)
+	{
+		return NOT_SUPPORTED;
+	}
+	return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid,
+				mark, tfc, lifetime, enc_alg, enc_key, int_alg, int_key, mode,
+				ipcomp, cpi, replay_window, initiator, encap, esn, inbound,
+				update, src_ts, dst_ts);
+}
+
+METHOD(kernel_interface_t, update_sa, status_t,
+	private_kernel_interface_t *this, u_int32_t spi, u_int8_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, mark_t mark)
+{
+	if (!this->ipsec)
+	{
+		return NOT_SUPPORTED;
+	}
+	return this->ipsec->update_sa(this->ipsec, spi, protocol, cpi, src, dst,
+								  new_src, new_dst, encap, new_encap, mark);
+}
+
+METHOD(kernel_interface_t, query_sa, status_t,
+	private_kernel_interface_t *this, host_t *src, host_t *dst,
+	u_int32_t spi, u_int8_t protocol, mark_t mark,
+	u_int64_t *bytes, u_int64_t *packets, time_t *time)
+{
+	if (!this->ipsec)
+	{
+		return NOT_SUPPORTED;
+	}
+	return this->ipsec->query_sa(this->ipsec, src, dst, spi, protocol, mark,
+								 bytes, packets, time);
+}
+
+METHOD(kernel_interface_t, del_sa, status_t,
+	private_kernel_interface_t *this, host_t *src, host_t *dst, u_int32_t spi,
+	u_int8_t protocol, u_int16_t cpi, mark_t mark)
+{
+	if (!this->ipsec)
+	{
+		return NOT_SUPPORTED;
+	}
+	return this->ipsec->del_sa(this->ipsec, src, dst, spi, protocol, cpi, mark);
+}
+
+METHOD(kernel_interface_t, flush_sas, status_t,
+	private_kernel_interface_t *this)
+{
+	if (!this->ipsec)
+	{
+		return NOT_SUPPORTED;
+	}
+	return this->ipsec->flush_sas(this->ipsec);
+}
+
+METHOD(kernel_interface_t, add_policy, status_t,
+	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, policy_type_t type, ipsec_sa_cfg_t *sa,
+	mark_t mark, policy_priority_t priority)
+{
+	if (!this->ipsec)
+	{
+		return NOT_SUPPORTED;
+	}
+	return this->ipsec->add_policy(this->ipsec, src, dst, src_ts, dst_ts,
+								   direction, type, sa, mark, priority);
+}
+
+METHOD(kernel_interface_t, query_policy, status_t,
+	private_kernel_interface_t *this, traffic_selector_t *src_ts,
+	traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+	time_t *use_time)
+{
+	if (!this->ipsec)
+	{
+		return NOT_SUPPORTED;
+	}
+	return this->ipsec->query_policy(this->ipsec, src_ts, dst_ts,
+									 direction, mark, use_time);
+}
+
+METHOD(kernel_interface_t, del_policy, status_t,
+	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, policy_type_t type, ipsec_sa_cfg_t *sa,
+	mark_t mark, policy_priority_t priority)
+{
+	if (!this->ipsec)
+	{
+		return NOT_SUPPORTED;
+	}
+	return this->ipsec->del_policy(this->ipsec, src, dst, src_ts, dst_ts,
+								   direction, type, sa, mark, priority);
+}
+
+METHOD(kernel_interface_t, flush_policies, status_t,
+	private_kernel_interface_t *this)
+{
+	if (!this->ipsec)
+	{
+		return NOT_SUPPORTED;
+	}
+	return this->ipsec->flush_policies(this->ipsec);
+}
+
+METHOD(kernel_interface_t, get_source_addr, host_t*,
+	private_kernel_interface_t *this, host_t *dest, host_t *src)
+{
+	if (!this->net)
+	{
+		return NULL;
+	}
+	return this->net->get_source_addr(this->net, dest, src);
+}
+
+METHOD(kernel_interface_t, get_nexthop, host_t*,
+	private_kernel_interface_t *this, host_t *dest, int prefix, host_t *src)
+{
+	if (!this->net)
+	{
+		return NULL;
+	}
+	return this->net->get_nexthop(this->net, dest, prefix, src);
+}
+
+METHOD(kernel_interface_t, get_interface, bool,
+	private_kernel_interface_t *this, host_t *host, char **name)
+{
+	if (!this->net)
+	{
+		return NULL;
+	}
+	return this->net->get_interface(this->net, host, name);
+}
+
+METHOD(kernel_interface_t, create_address_enumerator, enumerator_t*,
+	private_kernel_interface_t *this, kernel_address_type_t which)
+{
+	if (!this->net)
+	{
+		return enumerator_create_empty();
+	}
+	return this->net->create_address_enumerator(this->net, which);
+}
+
+METHOD(kernel_interface_t, add_ip, status_t,
+	private_kernel_interface_t *this, host_t *virtual_ip, int prefix,
+	char *iface)
+{
+	if (!this->net)
+	{
+		return NOT_SUPPORTED;
+	}
+	return this->net->add_ip(this->net, virtual_ip, prefix, iface);
+}
+
+METHOD(kernel_interface_t, del_ip, status_t,
+	private_kernel_interface_t *this, host_t *virtual_ip, int prefix, bool wait)
+{
+	if (!this->net)
+	{
+		return NOT_SUPPORTED;
+	}
+	return this->net->del_ip(this->net, virtual_ip, prefix, wait);
+}
+
+METHOD(kernel_interface_t, add_route, status_t,
+	private_kernel_interface_t *this, chunk_t dst_net,
+	u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name)
+{
+	if (!this->net)
+	{
+		return NOT_SUPPORTED;
+	}
+	return this->net->add_route(this->net, dst_net, prefixlen, gateway,
+								src_ip, if_name);
+}
+
+METHOD(kernel_interface_t, del_route, status_t,
+	private_kernel_interface_t *this, chunk_t dst_net,
+	u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name)
+{
+	if (!this->net)
+	{
+		return NOT_SUPPORTED;
+	}
+	return this->net->del_route(this->net, dst_net, prefixlen, gateway,
+								src_ip, if_name);
+}
+
+METHOD(kernel_interface_t, bypass_socket, bool,
+	private_kernel_interface_t *this, int fd, int family)
+{
+	if (!this->ipsec)
+	{
+		return FALSE;
+	}
+	return this->ipsec->bypass_socket(this->ipsec, fd, family);
+}
+
+METHOD(kernel_interface_t, enable_udp_decap, bool,
+	private_kernel_interface_t *this, int fd, int family, u_int16_t port)
+{
+	if (!this->ipsec)
+	{
+		return FALSE;
+	}
+	return this->ipsec->enable_udp_decap(this->ipsec, fd, family, port);
+}
+
+METHOD(kernel_interface_t, is_interface_usable, bool,
+	private_kernel_interface_t *this, const char *iface)
+{
+	status_t expected;
+
+	if (!this->ifaces_filter)
+	{
+		return TRUE;
+	}
+	expected = this->ifaces_exclude ? NOT_FOUND : SUCCESS;
+	return this->ifaces_filter->find_first(this->ifaces_filter, (void*)streq,
+										   NULL, iface) == expected;
+}
+
+METHOD(kernel_interface_t, all_interfaces_usable, bool,
+	private_kernel_interface_t *this)
+{
+	return this->ifaces_filter == NULL;
+}
+
+METHOD(kernel_interface_t, get_address_by_ts, status_t,
+	private_kernel_interface_t *this, traffic_selector_t *ts,
+	host_t **ip, bool *vip)
+{
+	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);
+
+	/* try virtual IPs only first (on all interfaces) */
+	addrs = create_address_enumerator(this,
+									  ADDR_TYPE_ALL ^ ADDR_TYPE_REGULAR);
+	while (addrs->enumerate(addrs, (void**)&host))
+	{
+		if (ts->includes(ts, host))
+		{
+			found = TRUE;
+			*ip = host->clone(host);
+			if (vip)
+			{
+				*vip = TRUE;
+			}
+			break;
+		}
+	}
+	addrs->destroy(addrs);
+
+	if (!found)
+	{	/* then try the regular addresses (on all interfaces) */
+		addrs = create_address_enumerator(this,
+										  ADDR_TYPE_ALL ^ ADDR_TYPE_VIRTUAL);
+		while (addrs->enumerate(addrs, (void**)&host))
+		{
+			if (ts->includes(ts, host))
+			{
+				found = TRUE;
+				*ip = host->clone(host);
+				if (vip)
+				{
+					*vip = FALSE;
+				}
+				break;
+			}
+		}
+		addrs->destroy(addrs);
+	}
+
+	if (!found)
+	{
+		DBG2(DBG_KNL, "no local address found in traffic selector %R", ts);
+		return FAILED;
+	}
+
+	DBG2(DBG_KNL, "using host %H", *ip);
+	return SUCCESS;
+}
+
+
+METHOD(kernel_interface_t, add_ipsec_interface, bool,
+	private_kernel_interface_t *this, kernel_ipsec_constructor_t constructor)
+{
+	if (!this->ipsec)
+	{
+		this->ipsec_constructor = constructor;
+		this->ipsec = constructor();
+		return this->ipsec != NULL;
+	}
+	return FALSE;
+}
+
+METHOD(kernel_interface_t, remove_ipsec_interface, bool,
+	private_kernel_interface_t *this, kernel_ipsec_constructor_t constructor)
+{
+	if (constructor == this->ipsec_constructor && this->ipsec)
+	{
+		this->ipsec->destroy(this->ipsec);
+		this->ipsec = NULL;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+METHOD(kernel_interface_t, add_net_interface, bool,
+	private_kernel_interface_t *this, kernel_net_constructor_t constructor)
+{
+	if (!this->net)
+	{
+		this->net_constructor = constructor;
+		this->net = constructor();
+		return this->net != NULL;
+	}
+	return FALSE;
+}
+
+METHOD(kernel_interface_t, remove_net_interface, bool,
+	private_kernel_interface_t *this, kernel_net_constructor_t constructor)
+{
+	if (constructor == this->net_constructor && this->net)
+	{
+		this->net->destroy(this->net);
+		this->net = NULL;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+METHOD(kernel_interface_t, add_listener, void,
+	private_kernel_interface_t *this, kernel_listener_t *listener)
+{
+	this->mutex->lock(this->mutex);
+	this->listeners->insert_last(this->listeners, listener);
+	this->mutex->unlock(this->mutex);
+}
+
+METHOD(kernel_interface_t, remove_listener, void,
+	private_kernel_interface_t *this, kernel_listener_t *listener)
+{
+	this->mutex->lock(this->mutex);
+	this->listeners->remove(this->listeners, listener, NULL);
+	this->mutex->unlock(this->mutex);
+}
+
+METHOD(kernel_interface_t, acquire, void,
+	private_kernel_interface_t *this, u_int32_t reqid,
+	traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
+{
+	kernel_listener_t *listener;
+	enumerator_t *enumerator;
+	this->mutex->lock(this->mutex);
+	enumerator = this->listeners->create_enumerator(this->listeners);
+	while (enumerator->enumerate(enumerator, &listener))
+	{
+		if (listener->acquire &&
+			!listener->acquire(listener, reqid, src_ts, dst_ts))
+		{
+			this->listeners->remove_at(this->listeners, enumerator);
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->mutex->unlock(this->mutex);
+}
+
+METHOD(kernel_interface_t, expire, void,
+	private_kernel_interface_t *this, u_int8_t protocol, u_int32_t spi,
+	host_t *dst, bool hard)
+{
+	kernel_listener_t *listener;
+	enumerator_t *enumerator;
+
+	this->mutex->lock(this->mutex);
+	enumerator = this->listeners->create_enumerator(this->listeners);
+	while (enumerator->enumerate(enumerator, &listener))
+	{
+		if (listener->expire &&
+			!listener->expire(listener, protocol, spi, dst, hard))
+		{
+			this->listeners->remove_at(this->listeners, enumerator);
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->mutex->unlock(this->mutex);
+}
+
+METHOD(kernel_interface_t, mapping, void,
+	private_kernel_interface_t *this, u_int8_t protocol, u_int32_t spi,
+	host_t *dst, host_t *remote)
+{
+	kernel_listener_t *listener;
+	enumerator_t *enumerator;
+
+	this->mutex->lock(this->mutex);
+	enumerator = this->listeners->create_enumerator(this->listeners);
+	while (enumerator->enumerate(enumerator, &listener))
+	{
+		if (listener->mapping &&
+			!listener->mapping(listener, protocol, spi, dst, remote))
+		{
+			this->listeners->remove_at(this->listeners, enumerator);
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->mutex->unlock(this->mutex);
+}
+
+METHOD(kernel_interface_t, migrate, void,
+	private_kernel_interface_t *this, u_int32_t reqid,
+	traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
+	policy_dir_t direction, host_t *local, host_t *remote)
+{
+	kernel_listener_t *listener;
+	enumerator_t *enumerator;
+	this->mutex->lock(this->mutex);
+	enumerator = this->listeners->create_enumerator(this->listeners);
+	while (enumerator->enumerate(enumerator, &listener))
+	{
+		if (listener->migrate &&
+			!listener->migrate(listener, reqid, src_ts, dst_ts, direction,
+							   local, remote))
+		{
+			this->listeners->remove_at(this->listeners, enumerator);
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->mutex->unlock(this->mutex);
+}
+
+static bool call_roam(kernel_listener_t *listener, bool *roam)
+{
+	return listener->roam && !listener->roam(listener, *roam);
+}
+
+METHOD(kernel_interface_t, roam, void,
+	private_kernel_interface_t *this, bool address)
+{
+	this->mutex->lock(this->mutex);
+	this->listeners->remove(this->listeners, &address, (void*)call_roam);
+	this->mutex->unlock(this->mutex);
+}
+
+METHOD(kernel_interface_t, tun, void,
+	private_kernel_interface_t *this, tun_device_t *tun, bool created)
+{
+	kernel_listener_t *listener;
+	enumerator_t *enumerator;
+	this->mutex->lock(this->mutex);
+	enumerator = this->listeners->create_enumerator(this->listeners);
+	while (enumerator->enumerate(enumerator, &listener))
+	{
+		if (listener->tun &&
+			!listener->tun(listener, tun, created))
+		{
+			this->listeners->remove_at(this->listeners, enumerator);
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->mutex->unlock(this->mutex);
+}
+
+METHOD(kernel_interface_t, register_algorithm, void,
+	private_kernel_interface_t *this, u_int16_t alg_id, transform_type_t type,
+	u_int16_t kernel_id, char *kernel_name)
+{
+	kernel_algorithm_t *algorithm;
+
+	INIT(algorithm,
+		.type = type,
+		.ike = alg_id,
+		.kernel = kernel_id,
+		.name = strdup(kernel_name),
+	);
+
+	this->mutex_algs->lock(this->mutex_algs);
+	this->algorithms->insert_first(this->algorithms, algorithm);
+	this->mutex_algs->unlock(this->mutex_algs);
+}
+
+METHOD(kernel_interface_t, lookup_algorithm, bool,
+	private_kernel_interface_t *this, u_int16_t alg_id, transform_type_t type,
+	u_int16_t *kernel_id, char **kernel_name)
+{
+	kernel_algorithm_t *algorithm;
+	enumerator_t *enumerator;
+	bool found = FALSE;
+
+	this->mutex_algs->lock(this->mutex_algs);
+	enumerator = this->algorithms->create_enumerator(this->algorithms);
+	while (enumerator->enumerate(enumerator, &algorithm))
+	{
+		if (algorithm->type == type && algorithm->ike == alg_id)
+		{
+			if (kernel_id)
+			{
+				*kernel_id = algorithm->kernel;
+			}
+			if (kernel_name)
+			{
+				*kernel_name = algorithm->name;
+			}
+			found = TRUE;
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->mutex_algs->unlock(this->mutex_algs);
+	return found;
+}
+
+METHOD(kernel_interface_t, destroy, void,
+	private_kernel_interface_t *this)
+{
+	kernel_algorithm_t *algorithm;
+
+	while (this->algorithms->remove_first(this->algorithms,
+										 (void**)&algorithm) == SUCCESS)
+	{
+		free(algorithm->name);
+		free(algorithm);
+	}
+	this->algorithms->destroy(this->algorithms);
+	this->mutex_algs->destroy(this->mutex_algs);
+	DESTROY_IF(this->ipsec);
+	DESTROY_IF(this->net);
+	DESTROY_FUNCTION_IF(this->ifaces_filter, (void*)free);
+	this->reqids->destroy(this->reqids);
+	this->reqids_by_ts->destroy(this->reqids_by_ts);
+	this->listeners->destroy(this->listeners);
+	this->mutex->destroy(this->mutex);
+	free(this);
+}
+
+/*
+ * Described in header-file
+ */
+kernel_interface_t *kernel_interface_create()
+{
+	private_kernel_interface_t *this;
+	char *ifaces;
+
+	INIT(this,
+		.public = {
+			.get_features = _get_features,
+			.get_spi = _get_spi,
+			.get_cpi = _get_cpi,
+			.alloc_reqid = _alloc_reqid,
+			.release_reqid = _release_reqid,
+			.add_sa = _add_sa,
+			.update_sa = _update_sa,
+			.query_sa = _query_sa,
+			.del_sa = _del_sa,
+			.flush_sas = _flush_sas,
+			.add_policy = _add_policy,
+			.query_policy = _query_policy,
+			.del_policy = _del_policy,
+			.flush_policies = _flush_policies,
+			.get_source_addr = _get_source_addr,
+			.get_nexthop = _get_nexthop,
+			.get_interface = _get_interface,
+			.create_address_enumerator = _create_address_enumerator,
+			.add_ip = _add_ip,
+			.del_ip = _del_ip,
+			.add_route = _add_route,
+			.del_route = _del_route,
+			.bypass_socket = _bypass_socket,
+			.enable_udp_decap = _enable_udp_decap,
+
+			.is_interface_usable = _is_interface_usable,
+			.all_interfaces_usable = _all_interfaces_usable,
+			.get_address_by_ts = _get_address_by_ts,
+			.add_ipsec_interface = _add_ipsec_interface,
+			.remove_ipsec_interface = _remove_ipsec_interface,
+			.add_net_interface = _add_net_interface,
+			.remove_net_interface = _remove_net_interface,
+
+			.add_listener = _add_listener,
+			.remove_listener = _remove_listener,
+			.register_algorithm = _register_algorithm,
+			.lookup_algorithm = _lookup_algorithm,
+			.acquire = _acquire,
+			.expire = _expire,
+			.mapping = _mapping,
+			.migrate = _migrate,
+			.roam = _roam,
+			.tun = _tun,
+			.destroy = _destroy,
+		},
+		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+		.listeners = linked_list_create(),
+		.mutex_algs = mutex_create(MUTEX_TYPE_DEFAULT),
+		.algorithms = linked_list_create(),
+		.reqids = hashtable_create((hashtable_hash_t)hash_reqid,
+								   (hashtable_equals_t)equals_reqid, 8),
+		.reqids_by_ts = hashtable_create((hashtable_hash_t)hash_reqid_by_ts,
+								   (hashtable_equals_t)equals_reqid_by_ts, 8),
+	);
+
+	ifaces = lib->settings->get_str(lib->settings,
+									"%s.interfaces_use", NULL, lib->ns);
+	if (!ifaces)
+	{
+		this->ifaces_exclude = TRUE;
+		ifaces = lib->settings->get_str(lib->settings,
+									"%s.interfaces_ignore", NULL, lib->ns);
+	}
+	if (ifaces)
+	{
+		enumerator_t *enumerator;
+		char *iface;
+
+		enumerator = enumerator_create_token(ifaces, ",", " ");
+		while (enumerator->enumerate(enumerator, &iface))
+		{
+			if (!this->ifaces_filter)
+			{
+				this->ifaces_filter = linked_list_create();
+			}
+			this->ifaces_filter->insert_last(this->ifaces_filter,
+											 strdup(iface));
+		}
+		enumerator->destroy(enumerator);
+	}
+
+	return &this->public;
+}
diff --git a/src/libcharon/kernel/kernel_interface.h b/src/libcharon/kernel/kernel_interface.h
new file mode 100644
index 0000000..6793c6c
--- /dev/null
+++ b/src/libcharon/kernel/kernel_interface.h
@@ -0,0 +1,655 @@
+/*
+ * Copyright (C) 2006-2015 Tobias Brunner
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+/*
+ * Copyright (c) 2012 Nanoteq Pty Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * @defgroup kernel_interface kernel_interface
+ * @{ @ingroup kernel
+ */
+
+#ifndef KERNEL_INTERFACE_H_
+#define KERNEL_INTERFACE_H_
+
+typedef struct kernel_interface_t kernel_interface_t;
+typedef enum kernel_feature_t kernel_feature_t;
+
+#include <networking/host.h>
+#include <crypto/prf_plus.h>
+
+#include <kernel/kernel_listener.h>
+#include <kernel/kernel_ipsec.h>
+#include <kernel/kernel_net.h>
+
+/**
+ * Bitfield of optional features a kernel backend supports.
+ *
+ * This feature-set is for both, kernel_ipsec_t and kernel_net_t. Each
+ * backend returns a subset of these features.
+ */
+enum kernel_feature_t {
+	/** IPsec can process ESPv3 (RFC 4303) TFC padded packets */
+	KERNEL_ESP_V3_TFC = (1<<0),
+	/** Networking requires an "exclude" route for IKE/ESP packets */
+	KERNEL_REQUIRE_EXCLUDE_ROUTE = (1<<1),
+	/** IPsec implementation requires UDP encapsulation of ESP packets */
+	KERNEL_REQUIRE_UDP_ENCAPSULATION = (1<<2),
+	/** IPsec backend does not require a policy reinstall on SA updates */
+	KERNEL_NO_POLICY_UPDATES = (1<<3),
+};
+
+/**
+ * Constructor function for ipsec kernel interface
+ */
+typedef kernel_ipsec_t* (*kernel_ipsec_constructor_t)(void);
+
+/**
+ * Constructor function for network kernel interface
+ */
+typedef kernel_net_t* (*kernel_net_constructor_t)(void);
+
+/**
+ * Manager and wrapper for different kernel interfaces.
+ *
+ * The kernel interface handles the communication with the kernel
+ * for SA and policy management and interface and IP address management.
+ */
+struct kernel_interface_t {
+
+	/**
+	 * Get the feature set supported by the net and ipsec kernel backends.
+	 *
+	 * @return				ORed feature-set of backends
+	 */
+	kernel_feature_t (*get_features)(kernel_interface_t *this);
+
+	/**
+	 * Get a SPI from the kernel.
+	 *
+	 * @param src		source address of SA
+	 * @param dst		destination address of SA
+	 * @param protocol	protocol for SA (ESP/AH)
+	 * @param spi		allocated spi
+	 * @return			SUCCESS if operation completed
+	 */
+	status_t (*get_spi)(kernel_interface_t *this, host_t *src, host_t *dst,
+						u_int8_t protocol, u_int32_t *spi);
+
+	/**
+	 * Get a Compression Parameter Index (CPI) from the kernel.
+	 *
+	 * @param src		source address of SA
+	 * @param dst		destination address of SA
+	 * @param cpi		allocated cpi
+	 * @return			SUCCESS if operation completed
+	 */
+	status_t (*get_cpi)(kernel_interface_t *this, host_t *src, host_t *dst,
+						u_int16_t *cpi);
+
+	/**
+	 * Allocate or confirm a reqid to use for a given SA pair.
+	 *
+	 * Each returned reqid by a successful call to alloc_reqid() must be
+	 * released using release_reqid().
+	 *
+	 * The reqid parameter is an in/out parameter. If it points to non-zero,
+	 * the reqid is confirmed and registered for use. If it points to zero,
+	 * a reqid is allocated for the given selectors, and returned to reqid.
+	 *
+	 * @param local_ts	traffic selectors of local side for SA
+	 * @param remote_ts	traffic selectors of remote side for SA
+	 * @param mark_in	inbound mark on SA
+	 * @param mark_out	outbound mark on SA
+	 * @param reqid		allocated reqid
+	 * @return			SUCCESS if reqid allocated
+	 */
+	status_t (*alloc_reqid)(kernel_interface_t *this,
+							linked_list_t *local_ts, linked_list_t *remote_ts,
+							mark_t mark_in, mark_t mark_out,
+							u_int32_t *reqid);
+
+	/**
+	 * Release a previously allocated reqid.
+	 *
+	 * @param reqid		reqid to release
+	 * @param mark_in	inbound mark on SA
+	 * @param mark_out	outbound mark on SA
+	 * @return			SUCCESS if reqid released
+	 */
+	status_t (*release_reqid)(kernel_interface_t *this, u_int32_t reqid,
+							  mark_t mark_in, mark_t mark_out);
+
+	/**
+	 * Add an SA to the SAD.
+	 *
+	 * This function does install a single SA for a single protocol in one
+	 * direction.
+	 *
+	 * @param src			source address for this 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 reqid			reqid for this SA
+	 * @param mark			optional mark for this SA
+	 * @param tfc			Traffic Flow Confidentiality padding for this SA
+	 * @param lifetime		lifetime_cfg_t for this SA
+	 * @param enc_alg		Algorithm to use for encryption (ESP only)
+	 * @param enc_key		key to use for encryption
+	 * @param int_alg		Algorithm to use for integrity protection
+	 * @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 replay_window	anti-replay window size
+	 * @param initiator		TRUE if initiator of the exchange creating this SA
+	 * @param encap			enable UDP encapsulation for NAT traversal
+	 * @param esn			TRUE to use Extended Sequence Numbers
+	 * @param inbound		TRUE if this is an inbound SA
+	 * @param update		TRUE if an SPI has already been allocated for SA
+	 * @param src_ts		list of source traffic selectors
+	 * @param dst_ts		list of destination traffic selectors
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*add_sa) (kernel_interface_t *this,
+						host_t *src, host_t *dst, u_int32_t spi,
+						u_int8_t protocol, u_int32_t reqid, mark_t mark,
+						u_int32_t tfc, lifetime_cfg_t *lifetime,
+						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,
+						u_int32_t replay_window, bool initiator, bool encap,
+						bool esn, bool inbound, bool update,
+						linked_list_t *src_ts, linked_list_t *dst_ts);
+
+	/**
+	 * Update the hosts on an installed SA.
+	 *
+	 * We cannot directly update the destination address as the kernel
+	 * requires the spi, the protocol AND the destination address (and family)
+	 * to identify SAs. Therefore if the destination address changed we
+	 * create a new SA and delete the old one.
+	 *
+	 * @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			current use of UDP encapsulation
+	 * @param new_encap		new use of UDP encapsulation
+	 * @param mark			optional mark for this SA
+	 * @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, u_int8_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, mark_t mark);
+
+	/**
+	 * Query the number of bytes processed by an SA from the SAD.
+	 *
+	 * @param src			source address for this 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 mark			optional mark for this SA
+	 * @param[out] bytes	the number of bytes processed by SA
+	 * @param[out] packets	number of packets processed by SA
+	 * @param[out] time		last (monotonic) time of SA use
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*query_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
+						  u_int32_t spi, u_int8_t protocol, mark_t mark,
+						  u_int64_t *bytes, u_int64_t *packets, time_t *time);
+
+	/**
+	 * Delete a previously installed SA from the SAD.
+	 *
+	 * @param src			source address for this 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 cpi			CPI for IPComp or 0
+	 * @param mark			optional mark for this SA
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*del_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
+						u_int32_t spi, u_int8_t protocol, u_int16_t cpi,
+						mark_t mark);
+
+	/**
+	 * Flush all SAs from the SAD.
+	 *
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*flush_sas) (kernel_interface_t *this);
+
+	/**
+	 * Add a policy to the SPD.
+	 *
+	 * @param src			source address of SA
+	 * @param dst			dest address of SA
+	 * @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|OUT|FWD)
+	 * @param type			type of policy, POLICY_(IPSEC|PASS|DROP)
+	 * @param sa			details about the SA(s) tied to this policy
+	 * @param mark			mark for this policy
+	 * @param priority		priority of this policy
+	 * @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, policy_type_t type,
+							ipsec_sa_cfg_t *sa, mark_t mark,
+							policy_priority_t priority);
+
+	/**
+	 * Query the use time of a policy.
+	 *
+	 * The use time of a policy is the time the policy was used
+	 * for the last time.
+	 *
+	 * @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|OUT|FWD)
+	 * @param mark			optional mark
+	 * @param[out] use_time	the (monotonic) time of this SA's last use
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*query_policy) (kernel_interface_t *this,
+							  traffic_selector_t *src_ts,
+							  traffic_selector_t *dst_ts,
+							  policy_dir_t direction, mark_t mark,
+							  time_t *use_time);
+
+	/**
+	 * Remove a policy from the SPD.
+	 *
+	 * @param src			source address of SA
+	 * @param dst			dest address of SA
+	 * @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|OUT|FWD)
+	 * @param type			type of policy, POLICY_(IPSEC|PASS|DROP)
+	 * @param sa			details about the SA(s) tied to this policy
+	 * @param mark			mark for this policy
+	 * @param priority		priority of the policy
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*del_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, policy_type_t type,
+							ipsec_sa_cfg_t *sa, mark_t mark,
+							policy_priority_t priority);
+
+	/**
+	 * Flush all policies from the SPD.
+	 *
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*flush_policies) (kernel_interface_t *this);
+
+	/**
+	 * Get our outgoing source address for a destination.
+	 *
+	 * Does a route lookup to get the source address used to reach dest.
+	 * The returned host is allocated and must be destroyed.
+	 * An optional src address can be used to check if a route is available
+	 * for the given source to dest.
+	 *
+	 * @param dest			target destination address
+	 * @param src			source address to check, or NULL
+	 * @return				outgoing source address, NULL if unreachable
+	 */
+	host_t* (*get_source_addr)(kernel_interface_t *this,
+							   host_t *dest, host_t *src);
+
+	/**
+	 * Get the next hop for a destination.
+	 *
+	 * Does a route lookup to get the next hop used to reach dest.
+	 * The returned host is allocated and must be destroyed.
+	 * An optional src address can be used to check if a route is available
+	 * for the given source to dest.
+	 *
+	 * @param dest			target destination address
+	 * @param prefix		prefix length if dest is a subnet, -1 for auto
+	 * @param src			source address to check, or NULL
+	 * @return				next hop address, NULL if unreachable
+	 */
+	host_t* (*get_nexthop)(kernel_interface_t *this, host_t *dest,
+						   int prefix, host_t *src);
+
+	/**
+	 * Get the interface name of a local address. Interfaces that are down or
+	 * ignored by config are not considered.
+	 *
+	 * @param host			address to get interface name from
+	 * @param name			allocated interface name (optional)
+	 * @return				TRUE if interface found and usable
+	 */
+	bool (*get_interface)(kernel_interface_t *this, host_t *host, char **name);
+
+	/**
+	 * Creates an enumerator over all local addresses.
+	 *
+	 * This function blocks an internal cached address list until the
+	 * enumerator gets destroyed.
+	 * The hosts are read-only, do not modify of free.
+	 *
+	 * @param which			a combination of address types to enumerate
+	 * @return				enumerator over host_t's
+	 */
+	enumerator_t *(*create_address_enumerator) (kernel_interface_t *this,
+												kernel_address_type_t which);
+
+	/**
+	 * Add a virtual IP to an interface.
+	 *
+	 * Virtual IPs are attached to an interface. If an IP is added multiple
+	 * times, the IP is refcounted and not removed until del_ip() was called
+	 * as many times as add_ip().
+	 *
+	 * @param virtual_ip	virtual ip address to assign
+	 * @param prefix		prefix length to install IP with, -1 for auto
+	 * @param iface			interface to install virtual IP on
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*add_ip) (kernel_interface_t *this, host_t *virtual_ip, int prefix,
+						char *iface);
+
+	/**
+	 * Remove a virtual IP from an interface.
+	 *
+	 * The kernel interface uses refcounting, see add_ip().
+	 *
+	 * @param virtual_ip	virtual ip address to remove
+	 * @param prefix		prefix length of the IP to uninstall, -1 for auto
+	 * @param wait			TRUE to wait untily IP is gone
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*del_ip) (kernel_interface_t *this, host_t *virtual_ip,
+						int prefix, bool wait);
+
+	/**
+	 * Add a route.
+	 *
+	 * @param dst_net		destination net
+	 * @param prefixlen		destination net prefix length
+	 * @param gateway		gateway for this route
+	 * @param src_ip		source ip of the route
+	 * @param if_name		name of the interface the route is bound to
+	 * @return				SUCCESS if operation completed
+	 *						ALREADY_DONE if the route already exists
+	 */
+	status_t (*add_route) (kernel_interface_t *this, chunk_t dst_net,
+						   u_int8_t prefixlen, host_t *gateway, host_t *src_ip,
+						   char *if_name);
+
+	/**
+	 * Delete a route.
+	 *
+	 * @param dst_net		destination net
+	 * @param prefixlen		destination net prefix length
+	 * @param gateway		gateway for this route
+	 * @param src_ip		source ip of the route
+	 * @param if_name		name of the interface the route is bound to
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*del_route) (kernel_interface_t *this, chunk_t dst_net,
+						   u_int8_t prefixlen, host_t *gateway, host_t *src_ip,
+						   char *if_name);
+
+	/**
+	 * Set up a bypass policy for a given socket.
+	 *
+	 * @param fd			socket file descriptor to setup policy for
+	 * @param family		protocol family of the socket
+	 * @return				TRUE if policy set up successfully
+	 */
+	bool (*bypass_socket)(kernel_interface_t *this, int fd, int family);
+
+	/**
+	 * Enable decapsulation of ESP-in-UDP packets for the given port/socket.
+	 *
+	 * @param fd			socket file descriptor
+	 * @param family		protocol family of the socket
+	 * @param port			the UDP port
+	 * @return				TRUE if UDP decapsulation was enabled successfully
+	 */
+	bool (*enable_udp_decap)(kernel_interface_t *this, int fd, int family,
+							 u_int16_t port);
+
+
+	/**
+	 * manager methods
+	 */
+
+	/**
+	 * Verifies that the given interface is usable and not excluded by
+	 * configuration.
+	 *
+	 * @param iface			interface name
+	 * @return				TRUE if usable
+	 */
+	bool (*is_interface_usable)(kernel_interface_t *this, const char *iface);
+
+	/**
+	 * Check if interfaces are excluded by config.
+	 *
+	 * @return				TRUE if no interfaces are exclued by config
+	 */
+	bool (*all_interfaces_usable)(kernel_interface_t *this);
+
+	/**
+	 * 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 address (has to be destroyed)
+	 * @param vip			set to TRUE if returned address is a virtual IP
+	 * @return				SUCCESS if address found
+	 */
+	status_t (*get_address_by_ts)(kernel_interface_t *this,
+								  traffic_selector_t *ts, host_t **ip, bool *vip);
+
+	/**
+	 * Register an ipsec kernel interface constructor on the manager.
+	 *
+	 * @param create		constructor to register
+	 * @return				TRUE if the ipsec kernel interface was registered
+	 *						successfully, FALSE if an interface was already
+	 *						registered or the registration failed
+	 */
+	bool (*add_ipsec_interface)(kernel_interface_t *this,
+								kernel_ipsec_constructor_t create);
+
+	/**
+	 * Unregister an ipsec kernel interface constructor.
+	 *
+	 * @param create		constructor to unregister
+	 * @return				TRUE if the ipsec kernel interface was unregistered
+	 *						successfully, FALSE otherwise
+	 */
+	bool (*remove_ipsec_interface)(kernel_interface_t *this,
+								   kernel_ipsec_constructor_t create);
+
+	/**
+	 * Register a network kernel interface constructor on the manager.
+	 *
+	 * @param create		constructor to register
+	 * @return				TRUE if the kernel net interface was registered
+	 *						successfully, FALSE if an interface was already
+	 *						registered or the registration failed
+	 */
+	bool (*add_net_interface)(kernel_interface_t *this,
+							  kernel_net_constructor_t create);
+
+	/**
+	 * Unregister a network kernel interface constructor.
+	 *
+	 * @param create		constructor to unregister
+	 * @return				TRUE if the kernel net interface was unregistered
+	 *						successfully, FALSE otherwise
+	 */
+	bool (*remove_net_interface)(kernel_interface_t *this,
+								 kernel_net_constructor_t create);
+
+	/**
+	 * Add a listener to the kernel interface.
+	 *
+	 * @param listener		listener to add
+	 */
+	void (*add_listener)(kernel_interface_t *this,
+						 kernel_listener_t *listener);
+
+	/**
+	 * Remove a listener from the kernel interface.
+	 *
+	 * @param listener		listener to remove
+	 */
+	void (*remove_listener)(kernel_interface_t *this,
+							kernel_listener_t *listener);
+
+	/**
+	 * Raise an acquire event.
+	 *
+	 * @param reqid			reqid of the policy to acquire
+	 * @param src_ts		source traffic selector
+	 * @param dst_ts		destination traffic selector
+	 */
+	void (*acquire)(kernel_interface_t *this, u_int32_t reqid,
+					traffic_selector_t *src_ts, traffic_selector_t *dst_ts);
+
+	/**
+	 * Raise an expire event.
+	 *
+	 * @param protocol		protocol of the expired SA
+	 * @param spi			spi of the expired SA
+	 * @param dst			destination address of expired SA
+	 * @param hard			TRUE if it is a hard expire, FALSE otherwise
+	 */
+	void (*expire)(kernel_interface_t *this, u_int8_t protocol, u_int32_t spi,
+				   host_t *dst, bool hard);
+
+	/**
+	 * Raise a mapping event.
+	 *
+	 * @param protocol		protocol of affected SA
+	 * @param spi			spi of the SA
+	 * @param dst			original destination address of SA
+	 * @param remote		new remote host
+	 */
+	void (*mapping)(kernel_interface_t *this, u_int8_t protocol, u_int32_t spi,
+					host_t *dst, host_t *remote);
+
+	/**
+	 * Raise a migrate event.
+	 *
+	 * @param reqid			reqid of the policy
+	 * @param src_ts		source traffic selector
+	 * @param dst_ts		destination traffic selector
+	 * @param direction		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
+	 */
+	void (*migrate)(kernel_interface_t *this, u_int32_t reqid,
+					traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
+					policy_dir_t direction, host_t *local, host_t *remote);
+
+	/**
+	 * Raise a roam event.
+	 *
+	 * @param address		TRUE if address list, FALSE if routing changed
+	 */
+	void (*roam)(kernel_interface_t *this, bool address);
+
+	/**
+	 * Raise a tun event.
+	 *
+	 * @param tun			TUN device
+	 * @param created		TRUE if created, FALSE if going to be destroyed
+	 */
+	void (*tun)(kernel_interface_t *this, tun_device_t *tun, bool created);
+
+	/**
+	 * Register a new algorithm with the kernel interface.
+	 *
+	 * @param alg_id			the IKE id of the algorithm
+	 * @param type				the transform type of the algorithm
+	 * @param kernel_id			the kernel id of the algorithm
+	 * @param kernel_name		the kernel name of the algorithm
+	 */
+	void (*register_algorithm)(kernel_interface_t *this, u_int16_t alg_id,
+							   transform_type_t type, u_int16_t kernel_id,
+							   char *kernel_name);
+
+	/**
+	 * Return the kernel-specific id and/or name for an algorithms depending on
+	 * the arguments specified.
+	 *
+	 * @param alg_id			the IKE id of the algorithm
+	 * @param type				the transform type of the algorithm
+	 * @param kernel_id			the kernel id of the algorithm (optional)
+	 * @param kernel_name		the kernel name of the algorithm (optional)
+	 * @return					TRUE if algorithm was found
+	 */
+	bool (*lookup_algorithm)(kernel_interface_t *this, u_int16_t alg_id,
+							 transform_type_t type, u_int16_t *kernel_id,
+							 char **kernel_name);
+
+	/**
+	 * Destroys a kernel_interface_t object.
+	 */
+	void (*destroy) (kernel_interface_t *this);
+};
+
+/**
+ * Creates an object of type kernel_interface_t.
+ */
+kernel_interface_t *kernel_interface_create(void);
+
+#endif /** KERNEL_INTERFACE_H_ @}*/
diff --git a/src/libcharon/kernel/kernel_ipsec.c b/src/libcharon/kernel/kernel_ipsec.c
new file mode 100644
index 0000000..0440f11
--- /dev/null
+++ b/src/libcharon/kernel/kernel_ipsec.c
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#include "kernel_ipsec.h"
+
+#include <daemon.h>
+
+/**
+ * See header
+ */
+bool kernel_ipsec_register(plugin_t *plugin, plugin_feature_t *feature,
+						   bool reg, void *data)
+{
+	if (reg)
+	{
+		return charon->kernel->add_ipsec_interface(charon->kernel,
+											(kernel_ipsec_constructor_t)data);
+	}
+	else
+	{
+		return charon->kernel->remove_ipsec_interface(charon->kernel,
+											(kernel_ipsec_constructor_t)data);
+	}
+}
diff --git a/src/libcharon/kernel/kernel_ipsec.h b/src/libcharon/kernel/kernel_ipsec.h
new file mode 100644
index 0000000..31e0630
--- /dev/null
+++ b/src/libcharon/kernel/kernel_ipsec.h
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2006-2015 Tobias Brunner
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 kernel_ipsec kernel_ipsec
+ * @{ @ingroup kernel
+ */
+
+#ifndef KERNEL_IPSEC_H_
+#define KERNEL_IPSEC_H_
+
+typedef struct kernel_ipsec_t kernel_ipsec_t;
+
+#include <networking/host.h>
+#include <ipsec/ipsec_types.h>
+#include <selectors/traffic_selector.h>
+#include <plugins/plugin.h>
+#include <kernel/kernel_interface.h>
+
+/**
+ * Interface to the ipsec subsystem of the kernel.
+ *
+ * The kernel ipsec interface handles the communication with the kernel
+ * for SA and policy management. It allows setup of these, and provides
+ * further the handling of kernel events.
+ * Policy information are cached in the interface. This is necessary to do
+ * reference counting. The Linux kernel does not allow the same policy
+ * installed twice, but we need this as CHILD_SA exist multiple times
+ * when rekeying. Thats why we do reference counting of policies.
+ */
+struct kernel_ipsec_t {
+
+	/**
+	 * Get the feature set supported by this kernel backend.
+	 *
+	 * @return				ORed feature-set of backend
+	 */
+	kernel_feature_t (*get_features)(kernel_ipsec_t *this);
+
+	/**
+	 * Get a SPI from the kernel.
+	 *
+	 * @param src		source address of SA
+	 * @param dst		destination address of SA
+	 * @param protocol	protocol for SA (ESP/AH)
+	 * @param spi		allocated spi
+	 * @return			SUCCESS if operation completed
+	 */
+	status_t (*get_spi)(kernel_ipsec_t *this, host_t *src, host_t *dst,
+						u_int8_t protocol, u_int32_t *spi);
+
+	/**
+	 * Get a Compression Parameter Index (CPI) from the kernel.
+	 *
+	 * @param src		source address of SA
+	 * @param dst		destination address of SA
+	 * @param cpi		allocated cpi
+	 * @return			SUCCESS if operation completed
+	 */
+	status_t (*get_cpi)(kernel_ipsec_t *this, host_t *src, host_t *dst,
+						u_int16_t *cpi);
+
+	/**
+	 * Add an SA to the SAD.
+	 *
+	 * This function does install a single SA for a single protocol in one
+	 * direction.
+	 *
+	 * @param src			source address for this 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 reqid			unique ID for this SA
+	 * @param mark			mark for this SA
+	 * @param tfc			Traffic Flow Confidentiality padding for this SA
+	 * @param lifetime		lifetime_cfg_t for this SA
+	 * @param enc_alg		Algorithm to use for encryption (ESP only)
+	 * @param enc_key		key to use for encryption
+	 * @param int_alg		Algorithm to use for integrity protection
+	 * @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 replay_window	anti-replay window size
+	 * @param initiator		TRUE if initiator of the exchange creating this SA
+	 * @param encap			enable UDP encapsulation for NAT traversal
+	 * @param esn			TRUE to use Extended Sequence Numbers
+	 * @param inbound		TRUE if this is an inbound SA
+	 * @param update		TRUE if an SPI has already been allocated for SA
+	 * @param src_ts		list of source traffic selectors
+	 * @param dst_ts		list of destination traffic selectors
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*add_sa) (kernel_ipsec_t *this,
+						host_t *src, host_t *dst, u_int32_t spi,
+						u_int8_t protocol, u_int32_t reqid,
+						mark_t mark, u_int32_t tfc, lifetime_cfg_t *lifetime,
+						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,
+						u_int32_t replay_window, bool initiator, bool encap,
+						bool esn, bool inbound, bool update,
+						linked_list_t *src_ts, linked_list_t *dst_ts);
+
+	/**
+	 * Update the hosts on an installed SA.
+	 *
+	 * We cannot directly update the destination address as the kernel
+	 * requires the spi, the protocol AND the destination address (and family)
+	 * to identify SAs. Therefore if the destination address changed we
+	 * create a new SA and delete the old one.
+	 *
+	 * @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			current use of UDP encapsulation
+	 * @param new_encap		new use of UDP encapsulation
+	 * @param mark			optional mark for this SA
+	 * @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, u_int8_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, mark_t mark);
+
+	/**
+	 * Query the number of bytes processed by an SA from the SAD.
+	 *
+	 * @param src			source address for this 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 mark			optional mark for this SA
+	 * @param[out] bytes	the number of bytes processed by SA
+	 * @param[out] packets	number of packets processed by SA
+	 * @param[out] time		last (monotonic) time of SA use
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*query_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
+						  u_int32_t spi, u_int8_t protocol, mark_t mark,
+						  u_int64_t *bytes, u_int64_t *packets, time_t *time);
+
+	/**
+	 * Delete a previusly installed SA from the SAD.
+	 *
+	 * @param src			source address for this 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 cpi			CPI for IPComp or 0
+	 * @param mark			optional mark for this SA
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*del_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
+						u_int32_t spi, u_int8_t protocol, u_int16_t cpi,
+						mark_t mark);
+
+	/**
+	 * Flush all SAs from the SAD.
+	 *
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*flush_sas) (kernel_ipsec_t *this);
+
+	/**
+	 * Add a policy to the SPD.
+	 *
+	 * @param src			source address of SA
+	 * @param dst			dest address of SA
+	 * @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|OUT|FWD)
+	 * @param type			type of policy, POLICY_(IPSEC|PASS|DROP)
+	 * @param sa			details about the SA(s) tied to this policy
+	 * @param mark			mark for this policy
+	 * @param priority		priority of this policy
+	 * @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, policy_type_t type,
+							ipsec_sa_cfg_t *sa, mark_t mark,
+							policy_priority_t priority);
+
+	/**
+	 * Query the use time of a policy.
+	 *
+	 * The use time of a policy is the time the policy was used for the last
+	 * time. It is not the system time, but a monotonic timestamp as returned
+	 * by time_monotonic.
+	 *
+	 * @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|OUT|FWD)
+	 * @param mark			optional mark
+	 * @param[out] use_time	the monotonic timestamp of this SA's last use
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*query_policy) (kernel_ipsec_t *this,
+							  traffic_selector_t *src_ts,
+							  traffic_selector_t *dst_ts,
+							  policy_dir_t direction, mark_t mark,
+							  time_t *use_time);
+
+	/**
+	 * Remove a policy from the SPD.
+	 *
+	 * @param src			source address of SA
+	 * @param dst			dest address of SA
+	 * @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|OUT|FWD)
+	 * @param type			type of policy, POLICY_(IPSEC|PASS|DROP)
+	 * @param sa			details about the SA(s) tied to this policy
+	 * @param mark			mark for this policy
+	 * @param priority		priority of the policy
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*del_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, policy_type_t type,
+							ipsec_sa_cfg_t *sa, mark_t mark,
+							policy_priority_t priority);
+
+	/**
+	 * Flush all policies from the SPD.
+	 *
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*flush_policies) (kernel_ipsec_t *this);
+
+	/**
+	 * Install a bypass policy for the given socket.
+	 *
+	 * @param fd			socket file descriptor to setup policy for
+	 * @param family		protocol family of the socket
+	 * @return				TRUE of policy set up successfully
+	 */
+	bool (*bypass_socket)(kernel_ipsec_t *this, int fd, int family);
+
+	/**
+	 * Enable decapsulation of ESP-in-UDP packets for the given port/socket.
+	 *
+	 * @param fd			socket file descriptor
+	 * @param family		protocol family of the socket
+	 * @param port			the UDP port
+	 * @return				TRUE if UDP decapsulation was enabled successfully
+	 */
+	bool (*enable_udp_decap)(kernel_ipsec_t *this, int fd, int family,
+							 u_int16_t port);
+
+	/**
+	 * Destroy the implementation.
+	 */
+	void (*destroy) (kernel_ipsec_t *this);
+};
+
+/**
+ * Helper function to (un-)register IPsec kernel interfaces from plugin features.
+ *
+ * This function is a plugin_feature_callback_t and can be used with the
+ * PLUGIN_CALLBACK macro to register an IPsec kernel interface constructor.
+ *
+ * @param plugin		plugin registering the kernel interface
+ * @param feature		associated plugin feature
+ * @param reg			TRUE to register, FALSE to unregister
+ * @param data			data passed to callback, an kernel_ipsec_constructor_t
+ */
+bool kernel_ipsec_register(plugin_t *plugin, plugin_feature_t *feature,
+						   bool reg, void *data);
+
+#endif /** KERNEL_IPSEC_H_ @}*/
diff --git a/src/libcharon/kernel/kernel_listener.h b/src/libcharon/kernel/kernel_listener.h
new file mode 100644
index 0000000..6426fae
--- /dev/null
+++ b/src/libcharon/kernel/kernel_listener.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2010-2013 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.
+ */
+
+/**
+ * @defgroup kernel_listener kernel_listener
+ * @{ @ingroup kernel
+ */
+
+#ifndef KERNEL_LISTENER_H_
+#define KERNEL_LISTENER_H_
+
+typedef struct kernel_listener_t kernel_listener_t;
+
+#include <networking/host.h>
+#include <networking/tun_device.h>
+#include <selectors/traffic_selector.h>
+#include <kernel/kernel_ipsec.h>
+
+/**
+ * Interface for components interested in kernel events.
+ *
+ * All hooks are optional.
+ */
+struct kernel_listener_t {
+
+	/**
+	 * Hook called if an acquire event for a policy is received.
+	 *
+	 * @param reqid			reqid of the policy to acquire
+	 * @param src_ts		source traffic selector
+	 * @param dst_ts		destination traffic selector
+	 * @return				TRUE to remain registered, FALSE to unregister
+	 */
+	bool (*acquire)(kernel_listener_t *this, u_int32_t reqid,
+					traffic_selector_t *src_ts, traffic_selector_t *dst_ts);
+
+	/**
+	 * Hook called if an exire event for an IPsec SA is received.
+	 *
+	 * @param protocol		protocol of the expired SA
+	 * @param spi			spi of the expired SA
+	 * @param dst			destination address of expired SA
+	 * @param hard			TRUE if it is a hard expire, FALSE otherwise
+	 * @return				TRUE to remain registered, FALSE to unregister
+	 */
+	bool (*expire)(kernel_listener_t *this, u_int8_t protocol, u_int32_t spi,
+				   host_t *dst, bool hard);
+
+	/**
+	 * Hook called if the NAT mappings of an IPsec SA changed.
+	 *
+	 * @param protocol		IPsec protocol of affected SA
+	 * @param spi			spi of the SA
+	 * @param dst			old destinatino address of SA
+	 * @param remote		new remote host
+	 * @return				TRUE to remain registered, FALSE to unregister
+	 */
+	bool (*mapping)(kernel_listener_t *this, u_int8_t protocol, u_int32_t spi,
+					host_t *dst, host_t *remote);
+
+	/**
+	 * Hook called if a migrate event for a policy is received.
+	 *
+	 * @param reqid			reqid of the policy
+	 * @param src_ts		source traffic selector
+	 * @param dst_ts		destination traffic selector
+	 * @param direction		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				TRUE to remain registered, FALSE to unregister
+	 */
+	bool (*migrate)(kernel_listener_t *this, u_int32_t reqid,
+					traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
+					policy_dir_t direction, host_t *local, host_t *remote);
+
+	/**
+	 * Hook called if changes in the networking layer occurred (interfaces
+	 * up/down, routes added/deleted etc.).
+	 *
+	 * @param address		TRUE if address list, FALSE if routing changed
+	 * @return				TRUE to remain registered, FALSE to unregister
+	 */
+	bool (*roam)(kernel_listener_t *this, bool address);
+
+	/**
+	 * Hook called after a TUN device was created for a virtual IP address, or
+	 * before such a device gets destroyed.
+	 *
+	 * @param tun			TUN device
+	 * @param created		TRUE if created, FALSE if going to be destroyed
+	 */
+	bool (*tun)(kernel_listener_t *this, tun_device_t *tun, bool created);
+};
+
+#endif /** KERNEL_LISTENER_H_ @}*/
diff --git a/src/libcharon/kernel/kernel_net.c b/src/libcharon/kernel/kernel_net.c
new file mode 100644
index 0000000..f169cad
--- /dev/null
+++ b/src/libcharon/kernel/kernel_net.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 revosec AG
+ *
+ * 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.
+ */
+
+#include "kernel_net.h"
+
+#include <daemon.h>
+
+/**
+ * See header
+ */
+bool kernel_net_register(plugin_t *plugin, plugin_feature_t *feature,
+						 bool reg, void *data)
+{
+	if (reg)
+	{
+		return charon->kernel->add_net_interface(charon->kernel,
+											(kernel_net_constructor_t)data);
+	}
+	else
+	{
+		return charon->kernel->remove_net_interface(charon->kernel,
+											(kernel_net_constructor_t)data);
+	}
+}
diff --git a/src/libcharon/kernel/kernel_net.h b/src/libcharon/kernel/kernel_net.h
new file mode 100644
index 0000000..7fc644a
--- /dev/null
+++ b/src/libcharon/kernel/kernel_net.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2008-2012 Tobias Brunner
+ * Copyright (C) 2007 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 kernel_net kernel_net
+ * @{ @ingroup kernel
+ */
+
+#ifndef KERNEL_NET_H_
+#define KERNEL_NET_H_
+
+typedef struct kernel_net_t kernel_net_t;
+typedef enum kernel_address_type_t kernel_address_type_t;
+
+#include <collections/enumerator.h>
+#include <networking/host.h>
+#include <plugins/plugin.h>
+#include <kernel/kernel_interface.h>
+
+/**
+ * Type of addresses (e.g. when enumerating them)
+ */
+enum kernel_address_type_t {
+	/** normal addresses (on regular, up, non-ignored) interfaces */
+	ADDR_TYPE_REGULAR = (1 << 0),
+	/** addresses on down interfaces */
+	ADDR_TYPE_DOWN =  (1 << 1),
+	/** addresses on ignored interfaces */
+	ADDR_TYPE_IGNORED = (1 << 2),
+	/** addresses on loopback interfaces */
+	ADDR_TYPE_LOOPBACK = (1 << 3),
+	/** virtual IP addresses */
+	ADDR_TYPE_VIRTUAL = (1 << 4),
+	/** to enumerate all available addresses */
+	ADDR_TYPE_ALL = (1 << 5) - 1,
+};
+
+/**
+ * Interface to the network subsystem of the kernel.
+ *
+ * The kernel network interface handles the communication with the kernel
+ * for interface and IP address management.
+ */
+struct kernel_net_t {
+
+	/**
+	 * Get the feature set supported by this kernel backend.
+	 *
+	 * @return				ORed feature-set of backend
+	 */
+	kernel_feature_t (*get_features)(kernel_net_t *this);
+
+	/**
+	 * Get our outgoing source address for a destination.
+	 *
+	 * Does a route lookup to get the source address used to reach dest.
+	 * The returned host is allocated and must be destroyed.
+	 * An optional src address can be used to check if a route is available
+	 * for the given source to dest.
+	 *
+	 * @param dest			target destination address
+	 * @param src			source address to check, or NULL
+	 * @return				outgoing source address, NULL if unreachable
+	 */
+	host_t* (*get_source_addr)(kernel_net_t *this, host_t *dest, host_t *src);
+
+	/**
+	 * Get the next hop for a destination.
+	 *
+	 * Does a route lookup to get the next hop used to reach dest.
+	 * The returned host is allocated and must be destroyed.
+	 * An optional src address can be used to check if a route is available
+	 * for the given source to dest.
+	 *
+	 * @param dest			target destination address
+	 * @param prefix		prefix length if dest is a subnet, -1 for auto
+	 * @param src			source address to check, or NULL
+	 * @return				next hop address, NULL if unreachable
+	 */
+	host_t* (*get_nexthop)(kernel_net_t *this, host_t *dest, int prefix,
+						   host_t *src);
+
+	/**
+	 * Get the interface name of a local address. Interfaces that are down or
+	 * ignored by config are not considered.
+	 *
+	 * @param host			address to get interface name from
+	 * @param name			allocated interface name (optional)
+	 * @return				TRUE if interface found and usable
+	 */
+	bool (*get_interface) (kernel_net_t *this, host_t *host, char **name);
+
+	/**
+	 * Creates an enumerator over all local addresses.
+	 *
+	 * This function blocks an internal cached address list until the
+	 * enumerator gets destroyed.
+	 * The hosts are read-only, do not modify of free.
+	 *
+	 * @param which			a combination of address types to enumerate
+	 * @return				enumerator over host_t's
+	 */
+	enumerator_t *(*create_address_enumerator) (kernel_net_t *this,
+												kernel_address_type_t which);
+
+	/**
+	 * Add a virtual IP to an interface.
+	 *
+	 * Virtual IPs are attached to an interface. If an IP is added multiple
+	 * times, the IP is refcounted and not removed until del_ip() was called
+	 * as many times as add_ip().
+	 *
+	 * @param virtual_ip	virtual ip address to assign
+	 * @param prefix		prefix length to install with IP address, -1 for auto
+	 * @param iface			interface to install virtual IP on
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*add_ip) (kernel_net_t *this, host_t *virtual_ip, int prefix,
+						char *iface);
+
+	/**
+	 * Remove a virtual IP from an interface.
+	 *
+	 * The kernel interface uses refcounting, see add_ip().
+	 *
+	 * @param virtual_ip	virtual ip address to remove
+	 * @param prefix		prefix length of the IP to uninstall, -1 for auto
+	 * @param wait			TRUE to wait until IP is gone
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*del_ip) (kernel_net_t *this, host_t *virtual_ip, int prefix,
+						bool wait);
+
+	/**
+	 * Add a route.
+	 *
+	 * @param dst_net		destination net
+	 * @param prefixlen		destination net prefix length
+	 * @param gateway		gateway for this route
+	 * @param src_ip		source ip of the route
+	 * @param if_name		name of the interface the route is bound to
+	 * @return				SUCCESS if operation completed
+	 *						ALREADY_DONE if the route already exists
+	 */
+	status_t (*add_route) (kernel_net_t *this, chunk_t dst_net,
+						   u_int8_t prefixlen, host_t *gateway, host_t *src_ip,
+						   char *if_name);
+
+	/**
+	 * Delete a route.
+	 *
+	 * @param dst_net		destination net
+	 * @param prefixlen		destination net prefix length
+	 * @param gateway		gateway for this route
+	 * @param src_ip		source ip of the route
+	 * @param if_name		name of the interface the route is bound to
+	 * @return				SUCCESS if operation completed
+	 */
+	status_t (*del_route) (kernel_net_t *this, chunk_t dst_net,
+						   u_int8_t prefixlen, host_t *gateway, host_t *src_ip,
+						   char *if_name);
+
+	/**
+	 * Destroy the implementation.
+	 */
+	void (*destroy) (kernel_net_t *this);
+};
+
+/**
+ * Helper function to (un-)register net kernel interfaces from plugin features.
+ *
+ * This function is a plugin_feature_callback_t and can be used with the
+ * PLUGIN_CALLBACK macro to register an net kernel interface constructor.
+ *
+ * @param plugin		plugin registering the kernel interface
+ * @param feature		associated plugin feature
+ * @param reg			TRUE to register, FALSE to unregister
+ * @param data			data passed to callback, an kernel_net_constructor_t
+ */
+bool kernel_net_register(plugin_t *plugin, plugin_feature_t *feature,
+						 bool reg, void *data);
+
+#endif /** KERNEL_NET_H_ @}*/
diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c
index a2f2016..ee357ca 100644
--- a/src/libcharon/network/receiver.c
+++ b/src/libcharon/network/receiver.c
@@ -20,7 +20,6 @@
 
 #include "receiver.h"
 
-#include <hydra.h>
 #include <daemon.h>
 #include <network/socket.h>
 #include <processing/jobs/job.h>
@@ -451,9 +450,8 @@ static job_requeue_t receive_packets(private_receiver_t *this)
 
 	dst = packet->get_destination(packet);
 	src = packet->get_source(packet);
-	if (!hydra->kernel_interface->all_interfaces_usable(hydra->kernel_interface)
-		&& !hydra->kernel_interface->get_interface(hydra->kernel_interface,
-												   dst, NULL))
+	if (!charon->kernel->all_interfaces_usable(charon->kernel)
+		&& !charon->kernel->get_interface(charon->kernel, dst, NULL))
 	{
 		DBG3(DBG_NET, "received packet from %#H to %#H on ignored interface",
 			 src, dst);
diff --git a/src/libcharon/plugins/addrblock/Makefile.am b/src/libcharon/plugins/addrblock/Makefile.am
index 33ee60d..ddb2706 100644
--- a/src/libcharon/plugins/addrblock/Makefile.am
+++ b/src/libcharon/plugins/addrblock/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/addrblock/Makefile.in b/src/libcharon/plugins/addrblock/Makefile.in
index 0554465..b4ae6fa 100644
--- a/src/libcharon/plugins/addrblock/Makefile.in
+++ b/src/libcharon/plugins/addrblock/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/android_dns/Makefile.am b/src/libcharon/plugins/android_dns/Makefile.am
index 1a0d6e6..e606a83 100644
--- a/src/libcharon/plugins/android_dns/Makefile.am
+++ b/src/libcharon/plugins/android_dns/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/android_dns/Makefile.in b/src/libcharon/plugins/android_dns/Makefile.in
index 58cf97b..d901498 100644
--- a/src/libcharon/plugins/android_dns/Makefile.in
+++ b/src/libcharon/plugins/android_dns/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/android_log/Makefile.am b/src/libcharon/plugins/android_log/Makefile.am
index 79c61b5..9f82f6e 100644
--- a/src/libcharon/plugins/android_log/Makefile.am
+++ b/src/libcharon/plugins/android_log/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/android_log/Makefile.in b/src/libcharon/plugins/android_log/Makefile.in
index 8ce92e5..64fecd9 100644
--- a/src/libcharon/plugins/android_log/Makefile.in
+++ b/src/libcharon/plugins/android_log/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/attr/Makefile.am b/src/libcharon/plugins/attr/Makefile.am
index 6bc7e77..ecbb76d 100644
--- a/src/libcharon/plugins/attr/Makefile.am
+++ b/src/libcharon/plugins/attr/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/attr/Makefile.in b/src/libcharon/plugins/attr/Makefile.in
index 486b3c0..acb7d07 100644
--- a/src/libcharon/plugins/attr/Makefile.in
+++ b/src/libcharon/plugins/attr/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -428,7 +430,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/attr/attr_provider.c b/src/libcharon/plugins/attr/attr_provider.c
index cac0ae4..1de571c 100644
--- a/src/libcharon/plugins/attr/attr_provider.c
+++ b/src/libcharon/plugins/attr/attr_provider.c
@@ -54,6 +54,8 @@ struct attribute_entry_t {
 	configuration_attribute_type_t type;
 	/** attribute value */
 	chunk_t value;
+	/** associated IKE version */
+	ike_version_t ike;
 };
 
 /**
@@ -66,26 +68,51 @@ static void attribute_destroy(attribute_entry_t *this)
 }
 
 /**
+ * Data for attribute enumerator
+ */
+typedef struct {
+	rwlock_t *lock;
+	ike_version_t ike;
+} enumerator_data_t;
+
+/**
  * convert enumerator value from attribute_entry
  */
-static bool attr_enum_filter(void *null, attribute_entry_t **in,
+static bool attr_enum_filter(enumerator_data_t *data, attribute_entry_t **in,
 			configuration_attribute_type_t *type, void* none, chunk_t *value)
 {
-	*type = (*in)->type;
-	*value = (*in)->value;
-	return TRUE;
+	if ((*in)->ike == IKE_ANY || (*in)->ike == data->ike)
+	{
+		*type = (*in)->type;
+		*value = (*in)->value;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+CALLBACK(attr_enum_destroy, void,
+	enumerator_data_t *data)
+{
+	data->lock->unlock(data->lock);
+	free(data);
 }
 
 METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
 	private_attr_provider_t *this, linked_list_t *pools,
 	ike_sa_t *ike_sa, linked_list_t *vips)
 {
+	enumerator_data_t *data;
+
 	if (vips->get_count(vips))
 	{
+		INIT(data,
+			.lock = this->lock,
+			.ike = ike_sa->get_version(ike_sa),
+		);
 		this->lock->read_lock(this->lock);
 		return enumerator_create_filter(
 				this->attributes->create_enumerator(this->attributes),
-				(void*)attr_enum_filter, this->lock, (void*)this->lock->unlock);
+				(void*)attr_enum_filter, data, attr_enum_destroy);
 	}
 	return enumerator_create_empty();
 }
@@ -116,8 +143,6 @@ static void add_legacy_entry(private_attr_provider_t *this, char *key, int nr,
 		host = host_create_from_string(str, 0);
 		if (host)
 		{
-			entry = malloc_thing(attribute_entry_t);
-
 			if (host->get_family(host) == AF_INET6)
 			{
 				switch (type)
@@ -132,8 +157,11 @@ static void add_legacy_entry(private_attr_provider_t *this, char *key, int nr,
 						break;
 				}
 			}
-			entry->type = type;
-			entry->value = chunk_clone(host->get_address(host));
+			INIT(entry,
+				.type = type,
+				.value = chunk_clone(host->get_address(host)),
+				.ike = IKE_ANY,
+			);
 			host->destroy(host);
 			DBG2(DBG_CFG, "loaded legacy entry attribute %N: %#B",
 				 configuration_attribute_type_names, entry->type, &entry->value);
@@ -149,18 +177,20 @@ typedef struct {
 	char *name;
 	configuration_attribute_type_t v4;
 	configuration_attribute_type_t v6;
+	ike_version_t ike;
 } attribute_type_key_t;
 
 static attribute_type_key_t keys[] = {
-	{"address",			INTERNAL_IP4_ADDRESS,	INTERNAL_IP6_ADDRESS},
-	{"dns",				INTERNAL_IP4_DNS,		INTERNAL_IP6_DNS},
-	{"nbns",			INTERNAL_IP4_NBNS,		INTERNAL_IP6_NBNS},
-	{"dhcp",			INTERNAL_IP4_DHCP,		INTERNAL_IP6_DHCP},
-	{"netmask",			INTERNAL_IP4_NETMASK,	INTERNAL_IP6_NETMASK},
-	{"server",			INTERNAL_IP4_SERVER,	INTERNAL_IP6_SERVER},
-	{"subnet",			INTERNAL_IP4_SUBNET,	INTERNAL_IP6_SUBNET},
-	{"split-include",	UNITY_SPLIT_INCLUDE,	UNITY_SPLIT_INCLUDE},
-	{"split-exclude",	UNITY_LOCAL_LAN,		UNITY_LOCAL_LAN},
+	{"address",			INTERNAL_IP4_ADDRESS,	INTERNAL_IP6_ADDRESS,	IKE_ANY},
+	{"dns",				INTERNAL_IP4_DNS,		INTERNAL_IP6_DNS,		IKE_ANY},
+	{"nbns",			INTERNAL_IP4_NBNS,		INTERNAL_IP6_NBNS,		IKE_ANY},
+	{"dhcp",			INTERNAL_IP4_DHCP,		INTERNAL_IP6_DHCP,		IKE_ANY},
+	{"netmask",			INTERNAL_IP4_NETMASK,	INTERNAL_IP6_NETMASK,	IKE_ANY},
+	{"server",			INTERNAL_IP4_SERVER,	INTERNAL_IP6_SERVER,	IKE_ANY},
+	{"subnet",			INTERNAL_IP4_SUBNET,	INTERNAL_IP6_SUBNET,	IKE_ANY},
+	{"p-cscf",			P_CSCF_IP4_ADDRESS,		P_CSCF_IP6_ADDRESS,		IKEV2},
+	{"split-include",	UNITY_SPLIT_INCLUDE,	UNITY_SPLIT_INCLUDE,	IKEV1},
+	{"split-exclude",	UNITY_LOCAL_LAN,		UNITY_LOCAL_LAN,		IKEV1},
 };
 
 /**
@@ -275,6 +305,7 @@ static void load_entries(private_attr_provider_t *this)
 			INIT(entry,
 				.type = type,
 				.value = data,
+				.ike = mapped ? mapped->ike : IKE_ANY,
 			);
 			DBG2(DBG_CFG, "loaded attribute %N: %#B",
 				 configuration_attribute_type_names, entry->type, &entry->value);
diff --git a/src/libcharon/plugins/attr_sql/Makefile.am b/src/libcharon/plugins/attr_sql/Makefile.am
index 366c902..e65ef36 100644
--- a/src/libcharon/plugins/attr_sql/Makefile.am
+++ b/src/libcharon/plugins/attr_sql/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/attr_sql/Makefile.in b/src/libcharon/plugins/attr_sql/Makefile.in
index 8f1b3c0..8ee9f3f 100644
--- a/src/libcharon/plugins/attr_sql/Makefile.in
+++ b/src/libcharon/plugins/attr_sql/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/certexpire/Makefile.am b/src/libcharon/plugins/certexpire/Makefile.am
index b8c241d..d2d38ef 100644
--- a/src/libcharon/plugins/certexpire/Makefile.am
+++ b/src/libcharon/plugins/certexpire/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
diff --git a/src/libcharon/plugins/certexpire/Makefile.in b/src/libcharon/plugins/certexpire/Makefile.in
index f946d73..be19d61 100644
--- a/src/libcharon/plugins/certexpire/Makefile.in
+++ b/src/libcharon/plugins/certexpire/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
diff --git a/src/libcharon/plugins/connmark/Makefile.am b/src/libcharon/plugins/connmark/Makefile.am
index cc4d0ec..561efa0 100644
--- a/src/libcharon/plugins/connmark/Makefile.am
+++ b/src/libcharon/plugins/connmark/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/connmark/Makefile.in b/src/libcharon/plugins/connmark/Makefile.in
index 65f53fd..eaf4f1e 100644
--- a/src/libcharon/plugins/connmark/Makefile.in
+++ b/src/libcharon/plugins/connmark/Makefile.in
@@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -432,7 +434,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/connmark/connmark_listener.c b/src/libcharon/plugins/connmark/connmark_listener.c
index 23df690..607316f 100644
--- a/src/libcharon/plugins/connmark/connmark_listener.c
+++ b/src/libcharon/plugins/connmark/connmark_listener.c
@@ -1,4 +1,7 @@
 /*
+ * Copyright (C) 2015 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
  * Copyright (C) 2014 Martin Willi
  * Copyright (C) 2014 revosec AG
  *
@@ -25,6 +28,14 @@
 #include <linux/netfilter/xt_policy.h>
 #include <linux/netfilter/xt_CONNMARK.h>
 
+/**
+ * Add a struct at the current position in the buffer
+ */
+#define ADD_STRUCT(pos, st, ...) ({\
+	typeof(pos) _cur = pos; pos += XT_ALIGN(sizeof(st));\
+	*(st*)_cur = (st){ __VA_ARGS__ };\
+	(st*)_cur;\
+})
 
 typedef struct private_connmark_listener_t private_connmark_listener_t;
 
@@ -90,7 +101,10 @@ static bool manage_rule(struct iptc_handle *ipth, const char *chain,
 	}
 	else
 	{
-		if (!iptc_delete_entry(chain, e, "", ipth))
+		u_char matchmask[e->next_offset];
+
+		memset(matchmask, 255, sizeof(matchmask));
+		if (!iptc_delete_entry(chain, e, matchmask, ipth))
 		{
 			DBG1(DBG_CFG, "deleting %s rule failed: %s",
 				 chain, iptc_strerror(errno));
@@ -108,54 +122,54 @@ static bool manage_pre_esp_in_udp(private_connmark_listener_t *this,
 								  u_int mark, u_int32_t spi,
 								  host_t *dst, host_t *src)
 {
-	struct {
-		struct ipt_entry e;
-		struct ipt_entry_match m;
-		struct xt_udp udp;
-		struct ipt_entry_target t;
-		struct xt_mark_tginfo2 tm;
-	} ipt = {
-		.e  = {
-			.target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) +
-									  sizeof(ipt.udp)),
-			.next_offset = sizeof(ipt),
-			.ip = {
-				.proto = IPPROTO_UDP,
-			},
+	u_int16_t match_size	= XT_ALIGN(sizeof(struct ipt_entry_match)) +
+							  XT_ALIGN(sizeof(struct xt_udp));
+	u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size;
+	u_int16_t target_size	= XT_ALIGN(sizeof(struct ipt_entry_target)) +
+							  XT_ALIGN(sizeof(struct xt_mark_tginfo2));
+	u_int16_t entry_size	= target_offset + target_size;
+	u_char ipt[entry_size], *pos = ipt;
+	struct ipt_entry *e;
+
+	memset(ipt, 0, sizeof(ipt));
+	e = ADD_STRUCT(pos, struct ipt_entry,
+		.target_offset = target_offset,
+		.next_offset = entry_size,
+		.ip = {
+			.proto = IPPROTO_UDP,
 		},
-		.m = {
-			.u = {
-				.user = {
-					.match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.udp)),
-					.name = "udp",
-				},
+	);
+	if (!host2in(dst, &e->ip.dst, &e->ip.dmsk) ||
+		!host2in(src, &e->ip.src, &e->ip.smsk))
+	{
+		return FALSE;
+	}
+	ADD_STRUCT(pos, struct ipt_entry_match,
+		.u = {
+			.user = {
+				.match_size = match_size,
+				.name = "udp",
 			},
 		},
-		.udp = {
-			.spts = { src->get_port(src), src->get_port(src) },
-			.dpts = { dst->get_port(dst), dst->get_port(dst) },
-		},
-		.t = {
-			.u = {
-				.user = {
-					.target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)),
-					.name = "MARK",
-					.revision = 2,
-				},
+	);
+	ADD_STRUCT(pos, struct xt_udp,
+		.spts = { src->get_port(src), src->get_port(src) },
+		.dpts = { dst->get_port(dst), dst->get_port(dst) },
+	);
+	ADD_STRUCT(pos, struct ipt_entry_target,
+		.u = {
+			.user = {
+				.target_size = target_size,
+				.name = "MARK",
+				.revision = 2,
 			},
 		},
-		.tm = {
-			.mark = mark,
-			.mask = ~0,
-		},
-	};
-
-	if (!host2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
-		!host2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk))
-	{
-		return FALSE;
-	}
-	return manage_rule(ipth, "PREROUTING", add, &ipt.e);
+	);
+	ADD_STRUCT(pos, struct xt_mark_tginfo2,
+		.mark = mark,
+		.mask = ~0,
+	);
+	return manage_rule(ipth, "PREROUTING", add, e);
 }
 
 /**
@@ -166,53 +180,53 @@ static bool manage_pre_esp(private_connmark_listener_t *this,
 						   u_int mark, u_int32_t spi,
 						   host_t *dst, host_t *src)
 {
-	struct {
-		struct ipt_entry e;
-		struct ipt_entry_match m;
-		struct xt_esp esp;
-		struct ipt_entry_target t;
-		struct xt_mark_tginfo2 tm;
-	} ipt = {
-		.e  = {
-			.target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) +
-									  sizeof(ipt.esp)),
-			.next_offset = sizeof(ipt),
-			.ip = {
-				.proto = IPPROTO_ESP,
-			},
+	u_int16_t match_size	= XT_ALIGN(sizeof(struct ipt_entry_match)) +
+							  XT_ALIGN(sizeof(struct xt_esp));
+	u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size;
+	u_int16_t target_size	= XT_ALIGN(sizeof(struct ipt_entry_target)) +
+							  XT_ALIGN(sizeof(struct xt_mark_tginfo2));
+	u_int16_t entry_size	= target_offset + target_size;
+	u_char ipt[entry_size], *pos = ipt;
+	struct ipt_entry *e;
+
+	memset(ipt, 0, sizeof(ipt));
+	e = ADD_STRUCT(pos, struct ipt_entry,
+		.target_offset = target_offset,
+		.next_offset = entry_size,
+		.ip = {
+			.proto = IPPROTO_ESP,
 		},
-		.m = {
-			.u = {
-				.user = {
-					.match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.esp)),
-					.name = "esp",
-				},
+	);
+	if (!host2in(dst, &e->ip.dst, &e->ip.dmsk) ||
+		!host2in(src, &e->ip.src, &e->ip.smsk))
+	{
+		return FALSE;
+	}
+	ADD_STRUCT(pos, struct ipt_entry_match,
+		.u = {
+			.user = {
+				.match_size = match_size,
+				.name = "esp",
 			},
 		},
-		.esp = {
-			.spis = { htonl(spi), htonl(spi) },
-		},
-		.t = {
-			.u = {
-				.user = {
-					.target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)),
-					.name = "MARK",
-					.revision = 2,
-				},
+	);
+	ADD_STRUCT(pos, struct xt_esp,
+		.spis = { htonl(spi), htonl(spi) },
+	);
+	ADD_STRUCT(pos, struct ipt_entry_target,
+		.u = {
+			.user = {
+				.target_size = target_size,
+				.name = "MARK",
+				.revision = 2,
 			},
 		},
-		.tm = {
-			.mark = mark,
-			.mask = ~0,
-		},
-	};
-
-	if (!host2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
-		!host2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk))
-	{
-		return FALSE;
-	}
-	return manage_rule(ipth, "PREROUTING", add, &ipt.e);
+	);
+	ADD_STRUCT(pos, struct xt_mark_tginfo2,
+		.mark = mark,
+		.mask = ~0,
+	);
+	return manage_rule(ipth, "PREROUTING", add, e);
 }
 
 /**
@@ -238,99 +252,115 @@ static bool manage_in(private_connmark_listener_t *this,
 					  u_int mark, u_int32_t spi,
 					  traffic_selector_t *dst, traffic_selector_t *src)
 {
-	struct {
-		struct ipt_entry e;
-		struct ipt_entry_match m;
-		struct xt_policy_info p;
-		struct ipt_entry_target t;
-		struct xt_connmark_tginfo1 cm;
-	} ipt = {
-		.e  = {
-			.target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) +
-									  sizeof(ipt.p)),
-			.next_offset = sizeof(ipt),
-		},
-		.m = {
-			.u = {
-				.user = {
-					.match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.p)),
-					.name = "policy",
-				},
+	u_int16_t match_size	= XT_ALIGN(sizeof(struct ipt_entry_match)) +
+							  XT_ALIGN(sizeof(struct xt_policy_info));
+	u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size;
+	u_int16_t target_size	= XT_ALIGN(sizeof(struct ipt_entry_target)) +
+							  XT_ALIGN(sizeof(struct xt_connmark_tginfo1));
+	u_int16_t entry_size	= target_offset + target_size;
+	u_char ipt[entry_size], *pos = ipt;
+	struct ipt_entry *e;
+
+	memset(ipt, 0, sizeof(ipt));
+	e = ADD_STRUCT(pos, struct ipt_entry,
+		.target_offset = target_offset,
+		.next_offset = entry_size,
+	);
+	if (!ts2in(dst, &e->ip.dst, &e->ip.dmsk) ||
+		!ts2in(src, &e->ip.src, &e->ip.smsk))
+	{
+		return FALSE;
+	}
+	ADD_STRUCT(pos, struct ipt_entry_match,
+		.u = {
+			.user = {
+				.match_size = match_size,
+				.name = "policy",
 			},
 		},
-		.p = {
-			.pol = {
-				{
-					.spi = spi,
-					.match.spi = 1,
-				},
+	);
+	ADD_STRUCT(pos, struct xt_policy_info,
+		.pol = {
+			{
+				.spi = spi,
+				.match.spi = 1,
 			},
-			.len = 1,
-			.flags = XT_POLICY_MATCH_IN,
 		},
-		.t = {
-			.u = {
-				.user = {
-					.target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.cm)),
-					.name = "CONNMARK",
-					.revision = 1,
-				},
+		.len = 1,
+		.flags = XT_POLICY_MATCH_IN,
+	);
+	ADD_STRUCT(pos, struct ipt_entry_target,
+		.u = {
+			.user = {
+				.target_size = target_size,
+				.name = "CONNMARK",
+				.revision = 1,
 			},
 		},
-		.cm = {
-			.ctmark = mark,
-			.ctmask = ~0,
-			.nfmask = ~0,
-			.mode = XT_CONNMARK_SET,
-		},
-	};
-
-	if (!ts2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
-		!ts2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk))
-	{
-		return FALSE;
-	}
-	return manage_rule(ipth, "INPUT", add, &ipt.e);
+	);
+	ADD_STRUCT(pos, struct xt_connmark_tginfo1,
+		.ctmark = mark,
+		.ctmask = ~0,
+		.nfmask = ~0,
+		.mode = XT_CONNMARK_SET,
+	);
+	return manage_rule(ipth, "INPUT", add, e);
 }
 
 /**
- * Add outbund rule restoring CONNMARK on matching traffic
+ * Add outbund rule restoring CONNMARK on matching traffic unless the packet
+ * already has a mark set
  */
 static bool manage_out(private_connmark_listener_t *this,
 					   struct iptc_handle *ipth, bool add,
 					   traffic_selector_t *dst, traffic_selector_t *src)
 {
-	struct {
-		struct ipt_entry e;
-		struct ipt_entry_target t;
-		struct xt_connmark_tginfo1 cm;
-	} ipt = {
-		.e  = {
-			.target_offset = XT_ALIGN(sizeof(ipt.e)),
-			.next_offset = sizeof(ipt),
-		},
-		.t = {
-			.u = {
-				.user = {
-					.target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.cm)),
-					.name = "CONNMARK",
-					.revision = 1,
-				},
-			},
-		},
-		.cm = {
-			.ctmask = ~0,
-			.nfmask = ~0,
-			.mode = XT_CONNMARK_RESTORE,
-		},
-	};
-
-	if (!ts2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
-		!ts2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk))
+	u_int16_t match_size	= XT_ALIGN(sizeof(struct ipt_entry_match)) +
+							  XT_ALIGN(sizeof(struct xt_mark_mtinfo1));
+	u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size;
+	u_int16_t target_size	= XT_ALIGN(sizeof(struct ipt_entry_target)) +
+							  XT_ALIGN(sizeof(struct xt_connmark_tginfo1));
+	u_int16_t entry_size	= target_offset + target_size;
+	u_char ipt[entry_size], *pos = ipt;
+	struct ipt_entry *e;
+
+	memset(ipt, 0, sizeof(ipt));
+	e = ADD_STRUCT(pos, struct ipt_entry,
+		.target_offset = target_offset,
+		.next_offset = entry_size,
+	);
+	if (!ts2in(dst, &e->ip.dst, &e->ip.dmsk) ||
+		!ts2in(src, &e->ip.src, &e->ip.smsk))
 	{
 		return FALSE;
 	}
-	return manage_rule(ipth, "OUTPUT", add, &ipt.e);
+	ADD_STRUCT(pos, struct ipt_entry_match,
+		.u = {
+			.user = {
+				.match_size = match_size,
+				.name = "mark",
+				.revision = 1,
+			},
+		},
+	);
+	ADD_STRUCT(pos, struct xt_mark_mtinfo1,
+		.mask = ~0,
+	);
+	ADD_STRUCT(pos, struct ipt_entry_target,
+		.u = {
+			.user = {
+				.target_size = target_size,
+				.name = "CONNMARK",
+				.revision = 1,
+			},
+		},
+	);
+	ADD_STRUCT(pos, struct xt_connmark_tginfo1,
+		.ctmask = ~0,
+		.nfmask = ~0,
+		.mode = XT_CONNMARK_RESTORE,
+	);
+	return manage_rule(ipth, "OUTPUT", add, e);
 }
 
 /**
diff --git a/src/libcharon/plugins/coupling/Makefile.am b/src/libcharon/plugins/coupling/Makefile.am
index badc7b7..62695aa 100644
--- a/src/libcharon/plugins/coupling/Makefile.am
+++ b/src/libcharon/plugins/coupling/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/coupling/Makefile.in b/src/libcharon/plugins/coupling/Makefile.in
index dff80c3..44598c3 100644
--- a/src/libcharon/plugins/coupling/Makefile.in
+++ b/src/libcharon/plugins/coupling/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/dhcp/Makefile.am b/src/libcharon/plugins/dhcp/Makefile.am
index 3c09db0..9ae68be 100644
--- a/src/libcharon/plugins/dhcp/Makefile.am
+++ b/src/libcharon/plugins/dhcp/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/dhcp/Makefile.in b/src/libcharon/plugins/dhcp/Makefile.in
index 1e84f04..3d39fda 100644
--- a/src/libcharon/plugins/dhcp/Makefile.in
+++ b/src/libcharon/plugins/dhcp/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -429,7 +431,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/dhcp/dhcp_socket.c b/src/libcharon/plugins/dhcp/dhcp_socket.c
index b8c1b40..0fd1d33 100644
--- a/src/libcharon/plugins/dhcp/dhcp_socket.c
+++ b/src/libcharon/plugins/dhcp/dhcp_socket.c
@@ -31,7 +31,6 @@
 #include <threading/condvar.h>
 #include <threading/thread.h>
 
-#include <hydra.h>
 #include <daemon.h>
 #include <processing/jobs/callback_job.h>
 
@@ -209,8 +208,7 @@ static int prepare_dhcp(private_dhcp_socket_t *this,
 	else
 	{
 		/* act as relay agent */
-		src = hydra->kernel_interface->get_source_addr(hydra->kernel_interface,
-													   this->dst, NULL);
+		src = charon->kernel->get_source_addr(charon->kernel, this->dst, NULL);
 		if (src)
 		{
 			memcpy(&dhcp->gateway_address, src->get_address(src).ptr,
diff --git a/src/libcharon/plugins/dnscert/Makefile.am b/src/libcharon/plugins/dnscert/Makefile.am
index 1455625..8181bfc 100644
--- a/src/libcharon/plugins/dnscert/Makefile.am
+++ b/src/libcharon/plugins/dnscert/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/dnscert/Makefile.in b/src/libcharon/plugins/dnscert/Makefile.in
index ed873b3..04fc31a 100644
--- a/src/libcharon/plugins/dnscert/Makefile.in
+++ b/src/libcharon/plugins/dnscert/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/duplicheck/Makefile.am b/src/libcharon/plugins/duplicheck/Makefile.am
index 338a114..32b850c 100644
--- a/src/libcharon/plugins/duplicheck/Makefile.am
+++ b/src/libcharon/plugins/duplicheck/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
diff --git a/src/libcharon/plugins/duplicheck/Makefile.in b/src/libcharon/plugins/duplicheck/Makefile.in
index 41862cb..da4534c 100644
--- a/src/libcharon/plugins/duplicheck/Makefile.in
+++ b/src/libcharon/plugins/duplicheck/Makefile.in
@@ -423,6 +423,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -438,7 +440,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
diff --git a/src/libcharon/plugins/duplicheck/duplicheck.c b/src/libcharon/plugins/duplicheck/duplicheck.c
index 508e8e3..7c4cd5c 100644
--- a/src/libcharon/plugins/duplicheck/duplicheck.c
+++ b/src/libcharon/plugins/duplicheck/duplicheck.c
@@ -19,8 +19,10 @@
 #include <stdlib.h>
 #include <stddef.h>
 #include <stdio.h>
+#include <string.h>
 #include <errno.h>
 #include <arpa/inet.h>
+#include <netinet/in.h>
 
 #include "duplicheck_msg.h"
 
diff --git a/src/libcharon/plugins/eap_aka/Makefile.am b/src/libcharon/plugins/eap_aka/Makefile.am
index 75e8eaf..5d7ab84 100644
--- a/src/libcharon/plugins/eap_aka/Makefile.am
+++ b/src/libcharon/plugins/eap_aka/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libsimaka
 
diff --git a/src/libcharon/plugins/eap_aka/Makefile.in b/src/libcharon/plugins/eap_aka/Makefile.in
index dacddfb..b5ffd8c 100644
--- a/src/libcharon/plugins/eap_aka/Makefile.in
+++ b/src/libcharon/plugins/eap_aka/Makefile.in
@@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -432,7 +434,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libsimaka
 
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am
index ec145a3..d68bfc4 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am
+++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libsimaka
 
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
index 3c26b85..e0ad6fe 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
+++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
@@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -433,7 +435,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libsimaka
 
diff --git a/src/libcharon/plugins/eap_dynamic/Makefile.am b/src/libcharon/plugins/eap_dynamic/Makefile.am
index 58b827a..fd08846 100644
--- a/src/libcharon/plugins/eap_dynamic/Makefile.am
+++ b/src/libcharon/plugins/eap_dynamic/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/eap_dynamic/Makefile.in b/src/libcharon/plugins/eap_dynamic/Makefile.in
index 402c7ca..821f6de 100644
--- a/src/libcharon/plugins/eap_dynamic/Makefile.in
+++ b/src/libcharon/plugins/eap_dynamic/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/eap_gtc/Makefile.am b/src/libcharon/plugins/eap_gtc/Makefile.am
index c3a12ba..a7d1f62 100644
--- a/src/libcharon/plugins/eap_gtc/Makefile.am
+++ b/src/libcharon/plugins/eap_gtc/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/eap_gtc/Makefile.in b/src/libcharon/plugins/eap_gtc/Makefile.in
index 2279b25..cfd7c4e 100644
--- a/src/libcharon/plugins/eap_gtc/Makefile.in
+++ b/src/libcharon/plugins/eap_gtc/Makefile.in
@@ -415,6 +415,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -430,7 +432,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/eap_identity/Makefile.am b/src/libcharon/plugins/eap_identity/Makefile.am
index 6c5b43f..4c44962 100644
--- a/src/libcharon/plugins/eap_identity/Makefile.am
+++ b/src/libcharon/plugins/eap_identity/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS =  \
diff --git a/src/libcharon/plugins/eap_identity/Makefile.in b/src/libcharon/plugins/eap_identity/Makefile.in
index 30d2c88..1c544f3 100644
--- a/src/libcharon/plugins/eap_identity/Makefile.in
+++ b/src/libcharon/plugins/eap_identity/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/eap_md5/Makefile.am b/src/libcharon/plugins/eap_md5/Makefile.am
index 16aa191..b27e8cc 100644
--- a/src/libcharon/plugins/eap_md5/Makefile.am
+++ b/src/libcharon/plugins/eap_md5/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/eap_md5/Makefile.in b/src/libcharon/plugins/eap_md5/Makefile.in
index 14616c2..e967262 100644
--- a/src/libcharon/plugins/eap_md5/Makefile.in
+++ b/src/libcharon/plugins/eap_md5/Makefile.in
@@ -415,6 +415,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -430,7 +432,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.am b/src/libcharon/plugins/eap_mschapv2/Makefile.am
index 4276a08..ded9bbe 100644
--- a/src/libcharon/plugins/eap_mschapv2/Makefile.am
+++ b/src/libcharon/plugins/eap_mschapv2/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.in b/src/libcharon/plugins/eap_mschapv2/Makefile.in
index 78dfd29..d96343a 100644
--- a/src/libcharon/plugins/eap_mschapv2/Makefile.in
+++ b/src/libcharon/plugins/eap_mschapv2/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/eap_peap/Makefile.am b/src/libcharon/plugins/eap_peap/Makefile.am
index 8960b84..ef22616 100644
--- a/src/libcharon/plugins/eap_peap/Makefile.am
+++ b/src/libcharon/plugins/eap_peap/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libtls
 
diff --git a/src/libcharon/plugins/eap_peap/Makefile.in b/src/libcharon/plugins/eap_peap/Makefile.in
index 2f0d65d..0f920fe 100644
--- a/src/libcharon/plugins/eap_peap/Makefile.in
+++ b/src/libcharon/plugins/eap_peap/Makefile.in
@@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -432,7 +434,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libtls
 
diff --git a/src/libcharon/plugins/eap_radius/Makefile.am b/src/libcharon/plugins/eap_radius/Makefile.am
index bc7a776..78cf991 100644
--- a/src/libcharon/plugins/eap_radius/Makefile.am
+++ b/src/libcharon/plugins/eap_radius/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libradius
 
diff --git a/src/libcharon/plugins/eap_radius/Makefile.in b/src/libcharon/plugins/eap_radius/Makefile.in
index 4753437..881a5b7 100644
--- a/src/libcharon/plugins/eap_radius/Makefile.in
+++ b/src/libcharon/plugins/eap_radius/Makefile.in
@@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -433,7 +435,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libradius
 
diff --git a/src/libcharon/plugins/eap_sim/Makefile.am b/src/libcharon/plugins/eap_sim/Makefile.am
index f681385..8d93077 100644
--- a/src/libcharon/plugins/eap_sim/Makefile.am
+++ b/src/libcharon/plugins/eap_sim/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libsimaka
 
diff --git a/src/libcharon/plugins/eap_sim/Makefile.in b/src/libcharon/plugins/eap_sim/Makefile.in
index 251eeee..aaa24bb 100644
--- a/src/libcharon/plugins/eap_sim/Makefile.in
+++ b/src/libcharon/plugins/eap_sim/Makefile.in
@@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -432,7 +434,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libsimaka
 
diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.am b/src/libcharon/plugins/eap_sim_file/Makefile.am
index c38e55e..5c5694c 100644
--- a/src/libcharon/plugins/eap_sim_file/Makefile.am
+++ b/src/libcharon/plugins/eap_sim_file/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libsimaka \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\"
diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.in b/src/libcharon/plugins/eap_sim_file/Makefile.in
index bffcbc0..6e61f99 100644
--- a/src/libcharon/plugins/eap_sim_file/Makefile.in
+++ b/src/libcharon/plugins/eap_sim_file/Makefile.in
@@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -433,7 +435,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libsimaka \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\"
diff --git a/src/libcharon/plugins/eap_sim_pcsc/Makefile.am b/src/libcharon/plugins/eap_sim_pcsc/Makefile.am
index 2292204..5e235e7 100644
--- a/src/libcharon/plugins/eap_sim_pcsc/Makefile.am
+++ b/src/libcharon/plugins/eap_sim_pcsc/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libsimaka
 
diff --git a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
index 78682ce..e821e3e 100644
--- a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
+++ b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
@@ -419,6 +419,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -434,7 +436,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libsimaka
 
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am
index f40efbd..c0d7b91 100644
--- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libsimaka
 
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
index 2a6be5f..b883f0a 100644
--- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
@@ -419,6 +419,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -434,7 +436,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libsimaka
 
diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.am b/src/libcharon/plugins/eap_simaka_reauth/Makefile.am
index 0fb6222..9e55bb1 100644
--- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.am
+++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libsimaka
 
diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
index de504d4..5417f96 100644
--- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
@@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -433,7 +435,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libsimaka
 
diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.am b/src/libcharon/plugins/eap_simaka_sql/Makefile.am
index b7d6fd4..f4c478d 100644
--- a/src/libcharon/plugins/eap_simaka_sql/Makefile.am
+++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libsimaka \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\"
diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.in b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
index de3508a..c858e46 100644
--- a/src/libcharon/plugins/eap_simaka_sql/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
@@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -432,7 +434,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libsimaka \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\"
diff --git a/src/libcharon/plugins/eap_tls/Makefile.am b/src/libcharon/plugins/eap_tls/Makefile.am
index 825beb8..551ecb3 100644
--- a/src/libcharon/plugins/eap_tls/Makefile.am
+++ b/src/libcharon/plugins/eap_tls/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libtls
 
diff --git a/src/libcharon/plugins/eap_tls/Makefile.in b/src/libcharon/plugins/eap_tls/Makefile.in
index d4219b8..c953d0e 100644
--- a/src/libcharon/plugins/eap_tls/Makefile.in
+++ b/src/libcharon/plugins/eap_tls/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libtls
 
diff --git a/src/libcharon/plugins/eap_tnc/Makefile.am b/src/libcharon/plugins/eap_tnc/Makefile.am
index 6fc78bc..186ae45 100644
--- a/src/libcharon/plugins/eap_tnc/Makefile.am
+++ b/src/libcharon/plugins/eap_tnc/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libtls \
 	-I$(top_srcdir)/src/libtncif \
diff --git a/src/libcharon/plugins/eap_tnc/Makefile.in b/src/libcharon/plugins/eap_tnc/Makefile.in
index 6c34ed0..2f197ed 100644
--- a/src/libcharon/plugins/eap_tnc/Makefile.in
+++ b/src/libcharon/plugins/eap_tnc/Makefile.in
@@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -432,7 +434,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libtls \
 	-I$(top_srcdir)/src/libtncif \
diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.c b/src/libcharon/plugins/eap_tnc/eap_tnc.c
index 350001b..621caff 100644
--- a/src/libcharon/plugins/eap_tnc/eap_tnc.c
+++ b/src/libcharon/plugins/eap_tnc/eap_tnc.c
@@ -328,7 +328,7 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
 	tnccs = tnc->tnccs->create_instance(tnc->tnccs, tnccs_type,
 						is_server, server, peer, server_ip, peer_ip,
 						(type == EAP_TNC) ? TNC_IFT_EAP_1_1 : TNC_IFT_EAP_2_0,
-						is_server ? enforce_recommendation : NULL);
+						enforce_recommendation);
 	if (!tnccs)
 	{
 		DBG1(DBG_TNC, "TNCCS protocol '%s' not enabled", protocol);
diff --git a/src/libcharon/plugins/eap_ttls/Makefile.am b/src/libcharon/plugins/eap_ttls/Makefile.am
index 3a7a8cd..3db20e3 100644
--- a/src/libcharon/plugins/eap_ttls/Makefile.am
+++ b/src/libcharon/plugins/eap_ttls/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libtls \
 	-I$(top_srcdir)/src/libradius
diff --git a/src/libcharon/plugins/eap_ttls/Makefile.in b/src/libcharon/plugins/eap_ttls/Makefile.in
index 0babf17..b563acd 100644
--- a/src/libcharon/plugins/eap_ttls/Makefile.in
+++ b/src/libcharon/plugins/eap_ttls/Makefile.in
@@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -433,7 +435,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libtls \
 	-I$(top_srcdir)/src/libradius
diff --git a/src/libcharon/plugins/error_notify/Makefile.am b/src/libcharon/plugins/error_notify/Makefile.am
index 1c64bd2..766bb4c 100644
--- a/src/libcharon/plugins/error_notify/Makefile.am
+++ b/src/libcharon/plugins/error_notify/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
diff --git a/src/libcharon/plugins/error_notify/Makefile.in b/src/libcharon/plugins/error_notify/Makefile.in
index 0a07aa7..03dfe3d 100644
--- a/src/libcharon/plugins/error_notify/Makefile.in
+++ b/src/libcharon/plugins/error_notify/Makefile.in
@@ -424,6 +424,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -439,7 +441,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
diff --git a/src/libcharon/plugins/ext_auth/Makefile.am b/src/libcharon/plugins/ext_auth/Makefile.am
index d51ea88..7028819 100644
--- a/src/libcharon/plugins/ext_auth/Makefile.am
+++ b/src/libcharon/plugins/ext_auth/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/ext_auth/Makefile.in b/src/libcharon/plugins/ext_auth/Makefile.in
index d23e680..fce2e8e 100644
--- a/src/libcharon/plugins/ext_auth/Makefile.in
+++ b/src/libcharon/plugins/ext_auth/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/farp/Makefile.am b/src/libcharon/plugins/farp/Makefile.am
index 0d862b0..6d96f3a 100644
--- a/src/libcharon/plugins/farp/Makefile.am
+++ b/src/libcharon/plugins/farp/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/farp/Makefile.in b/src/libcharon/plugins/farp/Makefile.in
index 318400f..2afc5ad 100644
--- a/src/libcharon/plugins/farp/Makefile.in
+++ b/src/libcharon/plugins/farp/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -429,7 +431,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/forecast/Makefile.am b/src/libcharon/plugins/forecast/Makefile.am
index ce57313..7753529 100644
--- a/src/libcharon/plugins/forecast/Makefile.am
+++ b/src/libcharon/plugins/forecast/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/forecast/Makefile.in b/src/libcharon/plugins/forecast/Makefile.in
index 7b190ca..4f2a407 100644
--- a/src/libcharon/plugins/forecast/Makefile.in
+++ b/src/libcharon/plugins/forecast/Makefile.in
@@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -432,7 +434,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/forecast/forecast_forwarder.c b/src/libcharon/plugins/forecast/forecast_forwarder.c
index 07a3d49..40aaa7f 100644
--- a/src/libcharon/plugins/forecast/forecast_forwarder.c
+++ b/src/libcharon/plugins/forecast/forecast_forwarder.c
@@ -27,7 +27,6 @@
 #include <ifaddrs.h>
 #include <net/if.h>
 
-#include <hydra.h>
 #include <daemon.h>
 #include <threading/thread.h>
 #include <processing/jobs/callback_job.h>
@@ -428,8 +427,7 @@ METHOD(forecast_forwarder_t, destroy, void,
 		lib->watcher->remove(lib->watcher, this->kernel.pkt);
 		close(this->kernel.pkt);
 	}
-	hydra->kernel_interface->remove_listener(hydra->kernel_interface,
-											 &this->kernel.listener);
+	charon->kernel->remove_listener(charon->kernel, &this->kernel.listener);
 	free(this);
 }
 
@@ -486,8 +484,8 @@ forecast_forwarder_t *forecast_forwarder_create(forecast_listener_t *listener)
 
 	setup_interface(&this->kernel);
 
-	hydra->kernel_interface->add_listener(hydra->kernel_interface,
-										  &this->kernel.listener);
+	charon->kernel->add_listener(charon->kernel,
+										   &this->kernel.listener);
 
 	lib->watcher->add(lib->watcher, this->kernel.pkt, WATCHER_READ,
 					  (watcher_cb_t)receive_casts, this);
diff --git a/src/libcharon/plugins/forecast/forecast_listener.c b/src/libcharon/plugins/forecast/forecast_listener.c
index 63a8cb1..8f7f260 100644
--- a/src/libcharon/plugins/forecast/forecast_listener.c
+++ b/src/libcharon/plugins/forecast/forecast_listener.c
@@ -1,4 +1,7 @@
 /*
+ * Copyright (C) 2015 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
  * Copyright (C) 2010-2014 Martin Willi
  * Copyright (C) 2010-2014 revosec AG
  *
@@ -25,6 +28,15 @@
 #include <collections/hashtable.h>
 #include <threading/rwlock.h>
 
+/**
+ * Add a struct at the current position in the buffer
+ */
+#define ADD_STRUCT(pos, st, ...) ({\
+	typeof(pos) _cur = pos; pos += XT_ALIGN(sizeof(st));\
+	*(st*)_cur = (st){ __VA_ARGS__ };\
+	(st*)_cur;\
+})
+
 typedef struct private_forecast_listener_t private_forecast_listener_t;
 
 /**
@@ -148,7 +160,10 @@ static bool manage_rule(struct iptc_handle *ipth, const char *chain,
 	}
 	else
 	{
-		if (!iptc_delete_entry(chain, e, "", ipth))
+		u_char matchmask[e->next_offset];
+
+		memset(matchmask, 255, sizeof(matchmask));
+		if (!iptc_delete_entry(chain, e, matchmask, ipth))
 		{
 			DBG1(DBG_CFG, "deleting %s rule failed: %s",
 				 chain, iptc_strerror(errno));
@@ -164,60 +179,60 @@ static bool manage_rule(struct iptc_handle *ipth, const char *chain,
 static bool manage_pre_esp_in_udp(struct iptc_handle *ipth,
 								  entry_t *entry, bool add)
 {
-	struct {
-		struct ipt_entry e;
-		struct ipt_entry_match m;
-		struct xt_udp udp;
-		struct ipt_entry_target t;
-		struct xt_mark_tginfo2 tm;
-	} ipt = {
-		.e  = {
-			.target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) +
-									  sizeof(ipt.udp)),
-			.next_offset = sizeof(ipt),
-			.ip = {
-				.proto = IPPROTO_UDP,
-			},
+	u_int16_t match_size	= XT_ALIGN(sizeof(struct ipt_entry_match)) +
+							  XT_ALIGN(sizeof(struct xt_udp));
+	u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size;
+	u_int16_t target_size	= XT_ALIGN(sizeof(struct ipt_entry_target)) +
+							  XT_ALIGN(sizeof(struct xt_mark_tginfo2));
+	u_int16_t entry_size	= target_offset + target_size;
+	u_char ipt[entry_size], *pos = ipt;
+	struct ipt_entry *e;
+
+	memset(ipt, 0, sizeof(ipt));
+	e = ADD_STRUCT(pos, struct ipt_entry,
+		.target_offset = target_offset,
+		.next_offset = entry_size,
+		.ip = {
+			.proto = IPPROTO_UDP,
 		},
-		.m = {
-			.u = {
-				.user = {
-					.match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.udp)),
-					.name = "udp",
-				},
+	);
+	if (!host2in(entry->lhost, &e->ip.dst, &e->ip.dmsk) ||
+		!host2in(entry->rhost, &e->ip.src, &e->ip.smsk))
+	{
+		return FALSE;
+	}
+	ADD_STRUCT(pos, struct ipt_entry_match,
+		.u = {
+			.user = {
+				.match_size = match_size,
+				.name = "udp",
 			},
 		},
-		.udp = {
-			.spts = {
-				entry->rhost->get_port(entry->rhost),
-				entry->rhost->get_port(entry->lhost)
-			},
-			.dpts = {
-				entry->lhost->get_port(entry->lhost),
-				entry->lhost->get_port(entry->lhost)
-			},
+	);
+	ADD_STRUCT(pos, struct xt_udp,
+		.spts = {
+			entry->rhost->get_port(entry->rhost),
+			entry->rhost->get_port(entry->lhost)
 		},
-		.t = {
-			.u = {
-				.user = {
-					.target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)),
-					.name = "MARK",
-					.revision = 2,
-				},
-			},
+		.dpts = {
+			entry->lhost->get_port(entry->lhost),
+			entry->lhost->get_port(entry->lhost)
 		},
-		.tm = {
-			.mark = entry->mark,
-			.mask = ~0,
+	);
+	ADD_STRUCT(pos, struct ipt_entry_target,
+		.u = {
+			.user = {
+				.target_size = target_size,
+				.name = "MARK",
+				.revision = 2,
+			},
 		},
-	};
-
-	if (!host2in(entry->lhost, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
-		!host2in(entry->rhost, &ipt.e.ip.src, &ipt.e.ip.smsk))
-	{
-		return FALSE;
-	}
-	return manage_rule(ipth, "PREROUTING", add, &ipt.e);
+	);
+	ADD_STRUCT(pos, struct xt_mark_tginfo2,
+		.mark = entry->mark,
+		.mask = ~0,
+	);
+	return manage_rule(ipth, "PREROUTING", add, e);
 }
 
 /**
@@ -225,53 +240,53 @@ static bool manage_pre_esp_in_udp(struct iptc_handle *ipth,
  */
 static bool manage_pre_esp(struct iptc_handle *ipth, entry_t *entry, bool add)
 {
-	struct {
-		struct ipt_entry e;
-		struct ipt_entry_match m;
-		struct xt_esp esp;
-		struct ipt_entry_target t;
-		struct xt_mark_tginfo2 tm;
-	} ipt = {
-		.e  = {
-			.target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) +
-									  sizeof(ipt.esp)),
-			.next_offset = sizeof(ipt),
-			.ip = {
-				.proto = IPPROTO_ESP,
-			},
+	u_int16_t match_size	= XT_ALIGN(sizeof(struct ipt_entry_match)) +
+							  XT_ALIGN(sizeof(struct xt_esp));
+	u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size;
+	u_int16_t target_size	= XT_ALIGN(sizeof(struct ipt_entry_target)) +
+							  XT_ALIGN(sizeof(struct xt_mark_tginfo2));
+	u_int16_t entry_size	= target_offset + target_size;
+	u_char ipt[entry_size], *pos = ipt;
+	struct ipt_entry *e;
+
+	memset(ipt, 0, sizeof(ipt));
+	e = ADD_STRUCT(pos, struct ipt_entry,
+		.target_offset = target_offset,
+		.next_offset = entry_size,
+		.ip = {
+			.proto = IPPROTO_ESP,
 		},
-		.m = {
-			.u = {
-				.user = {
-					.match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.esp)),
-					.name = "esp",
-				},
+	);
+	if (!host2in(entry->lhost, &e->ip.dst, &e->ip.dmsk) ||
+		!host2in(entry->rhost, &e->ip.src, &e->ip.smsk))
+	{
+		return FALSE;
+	}
+	ADD_STRUCT(pos, struct ipt_entry_match,
+		.u = {
+			.user = {
+				.match_size = match_size,
+				.name = "esp",
 			},
 		},
-		.esp = {
-			.spis = { htonl(entry->spi), htonl(entry->spi) },
-		},
-		.t = {
-			.u = {
-				.user = {
-					.target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)),
-					.name = "MARK",
-					.revision = 2,
-				},
+	);
+	ADD_STRUCT(pos, struct xt_esp,
+		.spis = { htonl(entry->spi), htonl(entry->spi) },
+	);
+	ADD_STRUCT(pos, struct ipt_entry_target,
+		.u = {
+			.user = {
+				.target_size = target_size,
+				.name = "MARK",
+				.revision = 2,
 			},
 		},
-		.tm = {
-			.mark = entry->mark,
-			.mask = ~0,
-		},
-	};
-
-	if (!host2in(entry->lhost, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
-		!host2in(entry->rhost, &ipt.e.ip.src, &ipt.e.ip.smsk))
-	{
-		return FALSE;
-	}
-	return manage_rule(ipth, "PREROUTING", add, &ipt.e);
+	);
+	ADD_STRUCT(pos, struct xt_mark_tginfo2,
+		.mark = entry->mark,
+		.mask = ~0,
+	);
+	return manage_rule(ipth, "PREROUTING", add, e);
 }
 
 /**
@@ -291,45 +306,52 @@ static bool manage_pre(struct iptc_handle *ipth, entry_t *entry, bool add)
  */
 static bool manage_out(struct iptc_handle *ipth, entry_t *entry, bool add)
 {
-	struct {
-		struct ipt_entry e;
-		struct ipt_entry_target t;
-		struct xt_mark_tginfo2 m;
-	} ipt = {
-		.e  = {
-			.target_offset = XT_ALIGN(sizeof(ipt.e)),
-			.next_offset = sizeof(ipt),
-		},
-		.t = {
-			.u.user.target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.m)),
-			.u.user.name = "MARK",
-			.u.user.revision = 2,
-		},
-		.m = {
-			.mark = entry->mark,
-			.mask = ~0,
+	u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry));
+	u_int16_t target_size	= XT_ALIGN(sizeof(struct ipt_entry_target)) +
+							  XT_ALIGN(sizeof(struct xt_mark_tginfo2));
+	u_int16_t entry_size	= target_offset + target_size;
+	u_char ipt[entry_size], *pos = ipt;
+	struct ipt_entry *e;
+
+	memset(ipt, 0, sizeof(ipt));
+	e = ADD_STRUCT(pos, struct ipt_entry,
+		.target_offset = target_offset,
+		.next_offset = entry_size,
+	);
+	ADD_STRUCT(pos, struct ipt_entry_target,
+		.u = {
+			.user = {
+				.target_size = target_size,
+				.name = "MARK",
+				.revision = 2,
+			},
 		},
-	};
+	);
+	ADD_STRUCT(pos, struct xt_mark_tginfo2,
+		.mark = entry->mark,
+		.mask = ~0,
+	);
+
 	enumerator_t *enumerator;
 	traffic_selector_t *ts;
 
 	enumerator = array_create_enumerator(entry->rts);
 	while (enumerator->enumerate(enumerator, &ts))
 	{
-		if (!ts2in(ts, &ipt.e.ip.dst, &ipt.e.ip.dmsk))
+		if (!ts2in(ts, &e->ip.dst, &e->ip.dmsk))
 		{
 			continue;
 		}
-		if (ipt.e.ip.dst.s_addr == 0xffffffff ||
-			ipt.e.ip.dst.s_addr == entry->broadcast ||
-			memeq(&ipt.e.ip.dst.s_addr, "\xe0", 1))
+		if (e->ip.dst.s_addr == 0xffffffff ||
+			e->ip.dst.s_addr == entry->broadcast ||
+			memeq(&e->ip.dst.s_addr, "\xe0", 1))
 		{
 			/* skip broadcast/multicast selectors, they are shared and the mark
 			 * is set by the socket we use for reinjection */
 			continue;
 		}
-		if (!manage_rule(ipth, "PREROUTING", add, &ipt.e) ||
-			!manage_rule(ipth, "OUTPUT", add, &ipt.e))
+		if (!manage_rule(ipth, "PREROUTING", add, e) ||
+			!manage_rule(ipth, "OUTPUT", add, e))
 		{
 			enumerator->destroy(enumerator);
 			return FALSE;
diff --git a/src/libcharon/plugins/ha/Makefile.am b/src/libcharon/plugins/ha/Makefile.am
index 50d3423..d501834 100644
--- a/src/libcharon/plugins/ha/Makefile.am
+++ b/src/libcharon/plugins/ha/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
diff --git a/src/libcharon/plugins/ha/Makefile.in b/src/libcharon/plugins/ha/Makefile.in
index de74f88c..677c36a 100644
--- a/src/libcharon/plugins/ha/Makefile.in
+++ b/src/libcharon/plugins/ha/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
diff --git a/src/libcharon/plugins/ha/ha_child.c b/src/libcharon/plugins/ha/ha_child.c
index dbb6adc..7dafb16 100644
--- a/src/libcharon/plugins/ha/ha_child.c
+++ b/src/libcharon/plugins/ha/ha_child.c
@@ -91,6 +91,10 @@ METHOD(listener_t, child_keys, bool,
 	{
 		m->add_attribute(m, HA_ALG_INTEG, alg);
 	}
+	if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &alg, NULL))
+	{
+		m->add_attribute(m, HA_ALG_DH, alg);
+	}
 	if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, &alg, NULL))
 	{
 		m->add_attribute(m, HA_ESN, alg);
diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c
index 07ef607..ce90f5b 100644
--- a/src/libcharon/plugins/ha/ha_dispatcher.c
+++ b/src/libcharon/plugins/ha/ha_dispatcher.c
@@ -132,6 +132,7 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
 	ike_sa_t *ike_sa = NULL, *old_sa = NULL;
 	ike_version_t version = IKEV2;
 	u_int16_t encr = 0, len = 0, integ = 0, prf = 0, old_prf = PRF_UNDEFINED;
+	u_int16_t dh_grp = 0;
 	chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty;
 	chunk_t secret = chunk_empty, old_skd = chunk_empty;
 	chunk_t dh_local = chunk_empty, dh_remote = chunk_empty, psk = chunk_empty;
@@ -193,6 +194,9 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
 			case HA_ALG_OLD_PRF:
 				old_prf = value.u16;
 				break;
+			case HA_ALG_DH:
+				dh_grp = value.u16;
+				break;
 			default:
 				break;
 		}
@@ -217,6 +221,10 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
 		{
 			proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, prf, 0);
 		}
+		if (dh_grp)
+		{
+			proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, dh_grp, 0);
+		}
 		charon->bus->set_sa(charon->bus, ike_sa);
 		dh = ha_diffie_hellman_create(secret, dh_local);
 		if (ike_sa->get_version(ike_sa) == IKEV2)
@@ -647,7 +655,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
 	u_int32_t inbound_spi = 0, outbound_spi = 0;
 	u_int16_t inbound_cpi = 0, outbound_cpi = 0;
 	u_int8_t mode = MODE_TUNNEL, ipcomp = 0;
-	u_int16_t encr = 0, integ = 0, len = 0;
+	u_int16_t encr = 0, integ = 0, len = 0, dh_grp = 0;
 	u_int16_t esn = NO_EXT_SEQ_NUMBERS;
 	u_int seg_i, seg_o;
 	chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty;
@@ -697,6 +705,9 @@ static void process_child_add(private_ha_dispatcher_t *this,
 			case HA_ALG_INTEG:
 				integ = value.u16;
 				break;
+			case HA_ALG_DH:
+				dh_grp = value.u16;
+				break;
 			case HA_ESN:
 				esn = value.u16;
 				break;
@@ -747,6 +758,10 @@ static void process_child_add(private_ha_dispatcher_t *this,
 	{
 		proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len);
 	}
+	if (dh_grp)
+	{
+		proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, dh_grp, 0);
+	}
 	proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, esn, 0);
 	if (secret.len)
 	{
diff --git a/src/libcharon/plugins/ha/ha_ike.c b/src/libcharon/plugins/ha/ha_ike.c
index 7492dd0..3ffcaee 100644
--- a/src/libcharon/plugins/ha/ha_ike.c
+++ b/src/libcharon/plugins/ha/ha_ike.c
@@ -121,6 +121,10 @@ METHOD(listener_t, ike_keys, bool,
 	{
 		m->add_attribute(m, HA_ALG_PRF, alg);
 	}
+	if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &alg, NULL))
+	{
+		m->add_attribute(m, HA_ALG_DH, alg);
+	}
 	m->add_attribute(m, HA_NONCE_I, nonce_i);
 	m->add_attribute(m, HA_NONCE_R, nonce_r);
 	m->add_attribute(m, HA_SECRET, secret);
@@ -310,27 +314,31 @@ METHOD(listener_t, message_hook, bool,
 			sync_vips(this, ike_sa);
 		}
 	}
-	if (!plain && ike_sa->get_version(ike_sa) == IKEV1)
+	if (ike_sa->get_version(ike_sa) == IKEV1)
 	{
 		ha_message_t *m;
 		keymat_v1_t *keymat;
-		u_int32_t mid;
 		chunk_t iv;
 
-		mid = message->get_message_id(message);
-		if (mid == 0)
+		/* we need the last block (or expected next IV) of Phase 1, which gets
+		 * upated after successful en-/decryption depending on direction */
+		if (incoming == plain)
 		{
-			keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
-			if (keymat->get_iv(keymat, mid, &iv))
+			if (message->get_message_id(message) == 0)
 			{
-				m = ha_message_create(HA_IKE_IV);
-				m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
-				m->add_attribute(m, HA_IV, iv);
-				this->socket->push(this->socket, m);
-				this->cache->cache(this->cache, ike_sa, m);
+				keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
+				if (keymat->get_iv(keymat, 0, &iv))
+				{
+					m = ha_message_create(HA_IKE_IV);
+					m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+					m->add_attribute(m, HA_IV, iv);
+					this->socket->push(this->socket, m);
+					this->cache->cache(this->cache, ike_sa, m);
+				}
 			}
 		}
-		if (!incoming && message->get_exchange_type(message) == TRANSACTION)
+		if (!plain && !incoming &&
+			message->get_exchange_type(message) == TRANSACTION)
 		{
 			sync_vips(this, ike_sa);
 		}
diff --git a/src/libcharon/plugins/ha/ha_message.c b/src/libcharon/plugins/ha/ha_message.c
index 6b00ed8..b40219c 100644
--- a/src/libcharon/plugins/ha/ha_message.c
+++ b/src/libcharon/plugins/ha/ha_message.c
@@ -230,6 +230,7 @@ METHOD(ha_message_t, add_attribute, void,
 			break;
 		}
 		/* u_int16_t */
+		case HA_ALG_DH:
 		case HA_ALG_PRF:
 		case HA_ALG_OLD_PRF:
 		case HA_ALG_ENCR:
@@ -450,6 +451,7 @@ METHOD(enumerator_t, attribute_enumerate, bool,
 			return TRUE;
 		}
 		/** u_int16_t */
+		case HA_ALG_DH:
 		case HA_ALG_PRF:
 		case HA_ALG_OLD_PRF:
 		case HA_ALG_ENCR:
diff --git a/src/libcharon/plugins/ha/ha_message.h b/src/libcharon/plugins/ha/ha_message.h
index 2ccb1fc..fe1786e 100644
--- a/src/libcharon/plugins/ha/ha_message.h
+++ b/src/libcharon/plugins/ha/ha_message.h
@@ -122,6 +122,8 @@ enum ha_message_attribute_t {
 	HA_ALG_ENCR_LEN,
 	/** u_int16_t, integrity protection algorithm */
 	HA_ALG_INTEG,
+	/** u_int16_t, DH group */
+	HA_ALG_DH,
 	/** u_int8_t, IPsec mode, TUNNEL|TRANSPORT|... */
 	HA_IPSEC_MODE,
 	/** u_int8_t, IPComp protocol */
diff --git a/src/libcharon/plugins/ipseckey/Makefile.am b/src/libcharon/plugins/ipseckey/Makefile.am
index aed63c1..b893300 100644
--- a/src/libcharon/plugins/ipseckey/Makefile.am
+++ b/src/libcharon/plugins/ipseckey/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/ipseckey/Makefile.in b/src/libcharon/plugins/ipseckey/Makefile.in
index f98e78f..0b7a291 100644
--- a/src/libcharon/plugins/ipseckey/Makefile.in
+++ b/src/libcharon/plugins/ipseckey/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/kernel_iph/Makefile.am b/src/libcharon/plugins/kernel_iph/Makefile.am
index 56946ae..7075701 100644
--- a/src/libcharon/plugins/kernel_iph/Makefile.am
+++ b/src/libcharon/plugins/kernel_iph/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/kernel_iph/Makefile.in b/src/libcharon/plugins/kernel_iph/Makefile.in
index 7a2583d..de5bfd5 100644
--- a/src/libcharon/plugins/kernel_iph/Makefile.in
+++ b/src/libcharon/plugins/kernel_iph/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/kernel_iph/kernel_iph_net.c b/src/libcharon/plugins/kernel_iph/kernel_iph_net.c
index a4be404..6a8a968 100644
--- a/src/libcharon/plugins/kernel_iph/kernel_iph_net.c
+++ b/src/libcharon/plugins/kernel_iph/kernel_iph_net.c
@@ -24,7 +24,7 @@
 
 #include "kernel_iph_net.h"
 
-#include <hydra.h>
+#include <daemon.h>
 #include <threading/mutex.h>
 #include <collections/linked_list.h>
 #include <processing/jobs/callback_job.h>
@@ -130,7 +130,7 @@ static job_requeue_t roam_event(private_kernel_iph_net_t *this)
 	this->roam_address = FALSE;
 	this->mutex->unlock(this->mutex);
 
-	hydra->kernel_interface->roam(hydra->kernel_interface, address);
+	charon->kernel->roam(charon->kernel, address);
 	return JOB_REQUEUE_NONE;
 }
 
diff --git a/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.c b/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.c
index c5475e3..c163814 100644
--- a/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.c
+++ b/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.c
@@ -17,8 +17,6 @@
 #include "kernel_iph_plugin.h"
 #include "kernel_iph_net.h"
 
-#include <hydra.h>
-
 typedef struct private_kernel_iph_plugin_t private_kernel_iph_plugin_t;
 
 /**
diff --git a/src/libcharon/plugins/kernel_libipsec/Makefile.am b/src/libcharon/plugins/kernel_libipsec/Makefile.am
index eca2b23..4757280 100644
--- a/src/libcharon/plugins/kernel_libipsec/Makefile.am
+++ b/src/libcharon/plugins/kernel_libipsec/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libipsec
 
diff --git a/src/libcharon/plugins/kernel_libipsec/Makefile.in b/src/libcharon/plugins/kernel_libipsec/Makefile.in
index 6b6c956..018a25a 100644
--- a/src/libcharon/plugins/kernel_libipsec/Makefile.in
+++ b/src/libcharon/plugins/kernel_libipsec/Makefile.in
@@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -433,7 +435,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libipsec
 
diff --git a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c
index d738e6d..4c8771e 100644
--- a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c
+++ b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c
@@ -17,7 +17,7 @@
 
 #include <library.h>
 #include <ipsec.h>
-#include <hydra.h>
+#include <daemon.h>
 #include <networking/tun_device.h>
 #include <threading/mutex.h>
 #include <utils/debug.h>
@@ -224,8 +224,7 @@ static inline bool policy_entry_equals(policy_entry_t *a,
  */
 static void expire(u_int8_t protocol, u_int32_t spi, host_t *dst, bool hard)
 {
-	hydra->kernel_interface->expire(hydra->kernel_interface, protocol,
-									spi, dst, hard);
+	charon->kernel->expire(charon->kernel, protocol, spi, dst, hard);
 }
 
 METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
@@ -313,16 +312,13 @@ static void add_exclude_route(private_kernel_libipsec_ipsec_t *this,
 	if (!route->exclude)
 	{
 		DBG2(DBG_KNL, "installing new exclude route for %H src %H", dst, src);
-		gtw = hydra->kernel_interface->get_nexthop(hydra->kernel_interface,
-												   dst, -1, NULL);
+		gtw = charon->kernel->get_nexthop(charon->kernel, dst, -1, NULL);
 		if (gtw)
 		{
 			char *if_name = NULL;
 
-			if (hydra->kernel_interface->get_interface(
-									hydra->kernel_interface, src, &if_name) &&
-				hydra->kernel_interface->add_route(hydra->kernel_interface,
-									dst->get_address(dst),
+			if (charon->kernel->get_interface(charon->kernel, src, &if_name) &&
+				charon->kernel->add_route(charon->kernel, dst->get_address(dst),
 									dst->get_family(dst) == AF_INET ? 32 : 128,
 									gtw, src, if_name) == SUCCESS)
 			{
@@ -367,14 +363,12 @@ static void remove_exclude_route(private_kernel_libipsec_ipsec_t *this,
 	dst = route->exclude->dst;
 	DBG2(DBG_KNL, "uninstalling exclude route for %H src %H",
 		 dst, route->exclude->src);
-	if (hydra->kernel_interface->get_interface(
-									hydra->kernel_interface,
-									route->exclude->src, &if_name) &&
-		hydra->kernel_interface->del_route(hydra->kernel_interface,
-									dst->get_address(dst),
-									dst->get_family(dst) == AF_INET ? 32 : 128,
-									route->exclude->gtw, route->exclude->src,
-									if_name) != SUCCESS)
+	if (charon->kernel->get_interface(charon->kernel, route->exclude->src,
+									  &if_name) &&
+		charon->kernel->del_route(charon->kernel, dst->get_address(dst),
+								  dst->get_family(dst) == AF_INET ? 32 : 128,
+								  route->exclude->gtw, route->exclude->src,
+								  if_name) != SUCCESS)
 	{
 		DBG1(DBG_KNL, "uninstalling exclude route for %H failed", dst);
 	}
@@ -402,8 +396,8 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this,
 		return TRUE;
 	}
 
-	if (hydra->kernel_interface->get_address_by_ts(hydra->kernel_interface,
-									src_ts, &src_ip, &is_virtual) != SUCCESS)
+	if (charon->kernel->get_address_by_ts(charon->kernel, src_ts, &src_ip,
+										  &is_virtual) != SUCCESS)
 	{
 		traffic_selector_t *multicast, *broadcast = NULL;
 		bool ignore = FALSE;
@@ -444,8 +438,7 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this,
 	);
 #ifndef __linux__
 	/* on Linux we cant't install a gateway */
-	route->gateway = hydra->kernel_interface->get_nexthop(
-										hydra->kernel_interface, dst, -1, src);
+	route->gateway = charon->kernel->get_nexthop(charon->kernel, dst, -1, src);
 #endif
 
 	if (policy->route)
@@ -459,9 +452,9 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this,
 			return TRUE;
 		}
 		/* uninstall previously installed route */
-		if (hydra->kernel_interface->del_route(hydra->kernel_interface,
-									old->dst_net, old->prefixlen, old->gateway,
-									old->src_ip, old->if_name) != SUCCESS)
+		if (charon->kernel->del_route(charon->kernel, old->dst_net,
+									  old->prefixlen, old->gateway,
+									  old->src_ip, old->if_name) != SUCCESS)
 		{
 			DBG1(DBG_KNL, "error uninstalling route installed with policy "
 				 "%R === %R %N", src_ts, dst_ts, policy_dir_names,
@@ -490,9 +483,9 @@ static bool install_route(private_kernel_libipsec_ipsec_t *this,
 	DBG2(DBG_KNL, "installing route: %R src %H dev %s",
 		 dst_ts, route->src_ip, route->if_name);
 
-	switch (hydra->kernel_interface->add_route(hydra->kernel_interface,
-							route->dst_net, route->prefixlen, route->gateway,
-							route->src_ip, route->if_name))
+	switch (charon->kernel->add_route(charon->kernel, route->dst_net,
+									  route->prefixlen, route->gateway,
+									  route->src_ip, route->if_name))
 	{
 		case ALREADY_DONE:
 			/* route exists, do not uninstall */
@@ -571,8 +564,8 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
 	policy_entry_t *policy, *found = NULL;
 	status_t status;
 
-	status = ipsec->policies->del_policy(ipsec->policies, src_ts, dst_ts,
-										 direction, sa->reqid, mark, priority);
+	status = ipsec->policies->del_policy(ipsec->policies, src, dst, src_ts,
+								dst_ts, direction, type, sa, mark, priority);
 
 	policy = create_policy_entry(src_ts, dst_ts, direction);
 
@@ -598,9 +591,9 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
 	{
 		route_entry_t *route = policy->route;
 
-		if (hydra->kernel_interface->del_route(hydra->kernel_interface,
-				route->dst_net, route->prefixlen, route->gateway, route->src_ip,
-				route->if_name) != SUCCESS)
+		if (charon->kernel->del_route(charon->kernel, 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,
@@ -629,9 +622,9 @@ METHOD(kernel_ipsec_t, flush_policies, status_t,
 		{
 			route_entry_t *route = pol->route;
 
-			hydra->kernel_interface->del_route(hydra->kernel_interface,
-					route->dst_net, route->prefixlen, route->gateway,
-					route->src_ip, route->if_name);
+			charon->kernel->del_route(charon->kernel, route->dst_net,
+									  route->prefixlen, route->gateway,
+									  route->src_ip, route->if_name);
 			remove_exclude_route(this, route);
 		}
 		policy_entry_destroy(pol);
diff --git a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_router.c b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_router.c
index 830954e..66141ad 100644
--- a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_router.c
+++ b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_router.c
@@ -19,7 +19,6 @@
 #include "kernel_libipsec_router.h"
 
 #include <daemon.h>
-#include <hydra.h>
 #include <ipsec.h>
 #include <collections/hashtable.h>
 #include <networking/tun_device.h>
@@ -298,8 +297,7 @@ METHOD(kernel_libipsec_router_t, destroy, void,
 										 (ipsec_outbound_cb_t)send_esp);
 	ipsec->processor->unregister_inbound(ipsec->processor,
 										 (ipsec_inbound_cb_t)deliver_plain);
-	hydra->kernel_interface->remove_listener(hydra->kernel_interface,
-											 &this->public.listener);
+	charon->kernel->remove_listener(charon->kernel, &this->public.listener);
 	this->lock->destroy(this->lock);
 	this->tuns->destroy(this->tuns);
 	close(this->notify[0]);
@@ -351,8 +349,7 @@ kernel_libipsec_router_t *kernel_libipsec_router_create()
 								  (hashtable_equals_t)tun_entry_equals, 4);
 	this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
 
-	hydra->kernel_interface->add_listener(hydra->kernel_interface,
-										  &this->public.listener);
+	charon->kernel->add_listener(charon->kernel, &this->public.listener);
 	ipsec->processor->register_outbound(ipsec->processor, send_esp, NULL);
 	ipsec->processor->register_inbound(ipsec->processor,
 									(ipsec_inbound_cb_t)deliver_plain, this);
diff --git a/src/libcharon/plugins/kernel_netlink/Makefile.am b/src/libcharon/plugins/kernel_netlink/Makefile.am
new file mode 100644
index 0000000..973e2c2
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/Makefile.am
@@ -0,0 +1,44 @@
+AM_CPPFLAGS = \
+	-I${linux_headers} \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libcharon \
+	-DROUTING_TABLE=${routing_table} \
+	-DROUTING_TABLE_PRIO=${routing_table_prio}
+
+AM_CFLAGS = \
+	$(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-kernel-netlink.la
+else
+plugin_LTLIBRARIES = libstrongswan-kernel-netlink.la
+endif
+
+libstrongswan_kernel_netlink_la_SOURCES = \
+	kernel_netlink_plugin.h kernel_netlink_plugin.c \
+	kernel_netlink_ipsec.h kernel_netlink_ipsec.c \
+	kernel_netlink_net.h kernel_netlink_net.c \
+	kernel_netlink_shared.h kernel_netlink_shared.c
+
+libstrongswan_kernel_netlink_la_LDFLAGS = -module -avoid-version
+
+
+TESTS = tests
+
+check_PROGRAMS = $(TESTS)
+
+tests_SOURCES = \
+	tests.h tests.c \
+	suites/test_socket.c \
+	kernel_netlink_shared.c
+
+tests_CFLAGS = \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libstrongswan/tests \
+	-DNETLINK_MSG_LOSS_HOOK=netlink_msg_loss \
+	@COVERAGE_CFLAGS@
+
+tests_LDFLAGS = @COVERAGE_LDFLAGS@
+tests_LDADD = \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(top_builddir)/src/libstrongswan/tests/libtest.la
diff --git a/src/libcharon/plugins/kernel_netlink/Makefile.in b/src/libcharon/plugins/kernel_netlink/Makefile.in
new file mode 100644
index 0000000..55dcabf
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/Makefile.in
@@ -0,0 +1,1007 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 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.
+
+ at SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@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@
+TESTS = tests$(EXEEXT)
+check_PROGRAMS = $(am__EXEEXT_1)
+subdir = src/libcharon/plugins/kernel_netlink
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+	$(top_srcdir)/m4/config/ltoptions.m4 \
+	$(top_srcdir)/m4/config/ltsugar.m4 \
+	$(top_srcdir)/m4/config/ltversion.m4 \
+	$(top_srcdir)/m4/config/lt~obsolete.m4 \
+	$(top_srcdir)/m4/macros/split-package-version.m4 \
+	$(top_srcdir)/m4/macros/with.m4 \
+	$(top_srcdir)/m4/macros/enable-disable.m4 \
+	$(top_srcdir)/m4/macros/add-plugin.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_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 = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_kernel_netlink_la_LIBADD =
+am_libstrongswan_kernel_netlink_la_OBJECTS = kernel_netlink_plugin.lo \
+	kernel_netlink_ipsec.lo kernel_netlink_net.lo \
+	kernel_netlink_shared.lo
+libstrongswan_kernel_netlink_la_OBJECTS =  \
+	$(am_libstrongswan_kernel_netlink_la_OBJECTS)
+AM_V_lt = $(am__v_lt_ at AM_V@)
+am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+libstrongswan_kernel_netlink_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) \
+	$(libstrongswan_kernel_netlink_la_LDFLAGS) $(LDFLAGS) -o $@
+ at MONOLITHIC_FALSE@am_libstrongswan_kernel_netlink_la_rpath = -rpath \
+ at MONOLITHIC_FALSE@	$(plugindir)
+ at MONOLITHIC_TRUE@am_libstrongswan_kernel_netlink_la_rpath =
+am__EXEEXT_1 = tests$(EXEEXT)
+am__dirstamp = $(am__leading_dot)dirstamp
+am_tests_OBJECTS = tests-tests.$(OBJEXT) \
+	suites/tests-test_socket.$(OBJEXT) \
+	tests-kernel_netlink_shared.$(OBJEXT)
+tests_OBJECTS = $(am_tests_OBJECTS)
+tests_DEPENDENCIES =  \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(top_builddir)/src/libstrongswan/tests/libtest.la
+tests_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(tests_CFLAGS) $(CFLAGS) \
+	$(tests_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_ at AM_V@)
+am__v_CC_ = $(am__v_CC_ at AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_ at AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_ at AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(libstrongswan_kernel_netlink_la_SOURCES) $(tests_SOURCES)
+DIST_SOURCES = $(libstrongswan_kernel_netlink_la_SOURCES) \
+	$(tests_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+  mgn= red= grn= lgn= blu= brg= std=; \
+  am__color_tests=no
+am__tty_colors = { \
+  $(am__tty_colors_dummy); \
+  if test "X$(AM_COLOR_TESTS)" = Xno; then \
+    am__color_tests=no; \
+  elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+    am__color_tests=yes; \
+  elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+    am__color_tests=yes; \
+  fi; \
+  if test $$am__color_tests = yes; then \
+    red=''; \
+    grn=''; \
+    lgn=''; \
+    blu=''; \
+    mgn=''; \
+    brg=''; \
+    std=''; \
+  fi; \
+}
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GEM = @GEM@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
+PTHREADLIB = @PTHREADLIB@
+PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+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_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+	-I${linux_headers} \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libcharon \
+	-DROUTING_TABLE=${routing_table} \
+	-DROUTING_TABLE_PRIO=${routing_table_prio}
+
+AM_CFLAGS = \
+	$(PLUGIN_CFLAGS)
+
+ at MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-kernel-netlink.la
+ at MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-kernel-netlink.la
+libstrongswan_kernel_netlink_la_SOURCES = \
+	kernel_netlink_plugin.h kernel_netlink_plugin.c \
+	kernel_netlink_ipsec.h kernel_netlink_ipsec.c \
+	kernel_netlink_net.h kernel_netlink_net.c \
+	kernel_netlink_shared.h kernel_netlink_shared.c
+
+libstrongswan_kernel_netlink_la_LDFLAGS = -module -avoid-version
+tests_SOURCES = \
+	tests.h tests.c \
+	suites/test_socket.c \
+	kernel_netlink_shared.c
+
+tests_CFLAGS = \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libstrongswan/tests \
+	-DNETLINK_MSG_LOSS_HOOK=netlink_msg_loss \
+	@COVERAGE_CFLAGS@
+
+tests_LDFLAGS = @COVERAGE_LDFLAGS@
+tests_LDADD = \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(top_builddir)/src/libstrongswan/tests/libtest.la
+
+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 ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_netlink/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_netlink/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
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+	}
+
+uninstall-pluginLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+	done
+
+clean-pluginLTLIBRARIES:
+	-test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+	@list='$(plugin_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+
+libstrongswan-kernel-netlink.la: $(libstrongswan_kernel_netlink_la_OBJECTS) $(libstrongswan_kernel_netlink_la_DEPENDENCIES) $(EXTRA_libstrongswan_kernel_netlink_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(libstrongswan_kernel_netlink_la_LINK) $(am_libstrongswan_kernel_netlink_la_rpath) $(libstrongswan_kernel_netlink_la_OBJECTS) $(libstrongswan_kernel_netlink_la_LIBADD) $(LIBS)
+
+clean-checkPROGRAMS:
+	@list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+suites/$(am__dirstamp):
+	@$(MKDIR_P) suites
+	@: > suites/$(am__dirstamp)
+suites/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) suites/$(DEPDIR)
+	@: > suites/$(DEPDIR)/$(am__dirstamp)
+suites/tests-test_socket.$(OBJEXT): suites/$(am__dirstamp) \
+	suites/$(DEPDIR)/$(am__dirstamp)
+
+tests$(EXEEXT): $(tests_OBJECTS) $(tests_DEPENDENCIES) $(EXTRA_tests_DEPENDENCIES) 
+	@rm -f tests$(EXEEXT)
+	$(AM_V_CCLD)$(tests_LINK) $(tests_OBJECTS) $(tests_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+	-rm -f suites/*.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_netlink_ipsec.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_netlink_net.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_netlink_plugin.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_netlink_shared.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/tests-kernel_netlink_shared.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/tests-tests.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/tests-test_socket.Po at am__quote@
+
+.c.o:
+ at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+ at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+ at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+ at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+ at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+ at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+ at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+tests-tests.o: tests.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT tests-tests.o -MD -MP -MF $(DEPDIR)/tests-tests.Tpo -c -o tests-tests.o `test -f 'tests.c' || echo '$(srcdir)/'`tests.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/tests-tests.Tpo $(DEPDIR)/tests-tests.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='tests.c' object='tests-tests.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o tests-tests.o `test -f 'tests.c' || echo '$(srcdir)/'`tests.c
+
+tests-tests.obj: tests.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT tests-tests.obj -MD -MP -MF $(DEPDIR)/tests-tests.Tpo -c -o tests-tests.obj `if test -f 'tests.c'; then $(CYGPATH_W) 'tests.c'; else $(CYGPATH_W) '$(srcdir)/tests.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/tests-tests.Tpo $(DEPDIR)/tests-tests.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='tests.c' object='tests-tests.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o tests-tests.obj `if test -f 'tests.c'; then $(CYGPATH_W) 'tests.c'; else $(CYGPATH_W) '$(srcdir)/tests.c'; fi`
+
+suites/tests-test_socket.o: suites/test_socket.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT suites/tests-test_socket.o -MD -MP -MF suites/$(DEPDIR)/tests-test_socket.Tpo -c -o suites/tests-test_socket.o `test -f 'suites/test_socket.c' || echo '$(srcdir)/'`suites/test_socket.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/tests-test_socket.Tpo suites/$(DEPDIR)/tests-test_socket.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_socket.c' object='suites/tests-test_socket.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o suites/tests-test_socket.o `test -f 'suites/test_socket.c' || echo '$(srcdir)/'`suites/test_socket.c
+
+suites/tests-test_socket.obj: suites/test_socket.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT suites/tests-test_socket.obj -MD -MP -MF suites/$(DEPDIR)/tests-test_socket.Tpo -c -o suites/tests-test_socket.obj `if test -f 'suites/test_socket.c'; then $(CYGPATH_W) 'suites/test_socket.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_socket.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/tests-test_socket.Tpo suites/$(DEPDIR)/tests-test_socket.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_socket.c' object='suites/tests-test_socket.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o suites/tests-test_socket.obj `if test -f 'suites/test_socket.c'; then $(CYGPATH_W) 'suites/test_socket.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_socket.c'; fi`
+
+tests-kernel_netlink_shared.o: kernel_netlink_shared.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT tests-kernel_netlink_shared.o -MD -MP -MF $(DEPDIR)/tests-kernel_netlink_shared.Tpo -c -o tests-kernel_netlink_shared.o `test -f 'kernel_netlink_shared.c' || echo '$(srcdir)/'`kernel_netlink_shared.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/tests-kernel_netlink_shared.Tpo $(DEPDIR)/tests-kernel_netlink_shared.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='kernel_netlink_shared.c' object='tests-kernel_netlink_shared.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o tests-kernel_netlink_shared.o `test -f 'kernel_netlink_shared.c' || echo '$(srcdir)/'`kernel_netlink_shared.c
+
+tests-kernel_netlink_shared.obj: kernel_netlink_shared.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT tests-kernel_netlink_shared.obj -MD -MP -MF $(DEPDIR)/tests-kernel_netlink_shared.Tpo -c -o tests-kernel_netlink_shared.obj `if test -f 'kernel_netlink_shared.c'; then $(CYGPATH_W) 'kernel_netlink_shared.c'; else $(CYGPATH_W) '$(srcdir)/kernel_netlink_shared.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/tests-kernel_netlink_shared.Tpo $(DEPDIR)/tests-kernel_netlink_shared.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='kernel_netlink_shared.c' object='tests-kernel_netlink_shared.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o tests-kernel_netlink_shared.obj `if test -f 'kernel_netlink_shared.c'; then $(CYGPATH_W) 'kernel_netlink_shared.c'; else $(CYGPATH_W) '$(srcdir)/kernel_netlink_shared.c'; fi`
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+	@failed=0; all=0; xfail=0; xpass=0; skip=0; \
+	srcdir=$(srcdir); export srcdir; \
+	list=' $(TESTS) '; \
+	$(am__tty_colors); \
+	if test -n "$$list"; then \
+	  for tst in $$list; do \
+	    if test -f ./$$tst; then dir=./; \
+	    elif test -f $$tst; then dir=; \
+	    else dir="$(srcdir)/"; fi; \
+	    if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *[\ \	]$$tst[\ \	]*) \
+		xpass=`expr $$xpass + 1`; \
+		failed=`expr $$failed + 1`; \
+		col=$$red; res=XPASS; \
+	      ;; \
+	      *) \
+		col=$$grn; res=PASS; \
+	      ;; \
+	      esac; \
+	    elif test $$? -ne 77; then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *[\ \	]$$tst[\ \	]*) \
+		xfail=`expr $$xfail + 1`; \
+		col=$$lgn; res=XFAIL; \
+	      ;; \
+	      *) \
+		failed=`expr $$failed + 1`; \
+		col=$$red; res=FAIL; \
+	      ;; \
+	      esac; \
+	    else \
+	      skip=`expr $$skip + 1`; \
+	      col=$$blu; res=SKIP; \
+	    fi; \
+	    echo "$${col}$$res$${std}: $$tst"; \
+	  done; \
+	  if test "$$all" -eq 1; then \
+	    tests="test"; \
+	    All=""; \
+	  else \
+	    tests="tests"; \
+	    All="All "; \
+	  fi; \
+	  if test "$$failed" -eq 0; then \
+	    if test "$$xfail" -eq 0; then \
+	      banner="$$All$$all $$tests passed"; \
+	    else \
+	      if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+	      banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+	    fi; \
+	  else \
+	    if test "$$xpass" -eq 0; then \
+	      banner="$$failed of $$all $$tests failed"; \
+	    else \
+	      if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+	      banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+	    fi; \
+	  fi; \
+	  dashes="$$banner"; \
+	  skipped=""; \
+	  if test "$$skip" -ne 0; then \
+	    if test "$$skip" -eq 1; then \
+	      skipped="($$skip test was not run)"; \
+	    else \
+	      skipped="($$skip tests were not run)"; \
+	    fi; \
+	    test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$skipped"; \
+	  fi; \
+	  report=""; \
+	  if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+	    report="Please report to $(PACKAGE_BUGREPORT)"; \
+	    test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$report"; \
+	  fi; \
+	  dashes=`echo "$$dashes" | sed s/./=/g`; \
+	  if test "$$failed" -eq 0; then \
+	    col="$$grn"; \
+	  else \
+	    col="$$red"; \
+	  fi; \
+	  echo "$${col}$$dashes$${std}"; \
+	  echo "$${col}$$banner$${std}"; \
+	  test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
+	  test -z "$$report" || echo "$${col}$$report$${std}"; \
+	  echo "$${col}$$dashes$${std}"; \
+	  test "$$failed" -eq 0; \
+	else :; fi
+
+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 "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$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
+	$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+	$(MAKE) $(AM_MAKEFLAGS) check-TESTS
+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:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+	-rm -f suites/$(DEPDIR)/$(am__dirstamp)
+	-rm -f suites/$(am__dirstamp)
+
+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-checkPROGRAMS clean-generic clean-libtool \
+	clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR) suites/$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR) suites/$(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: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \
+	clean-checkPROGRAMS clean-generic clean-libtool \
+	clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES cscopelist-am \
+	ctags ctags-am 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 tags-am 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/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
new file mode 100644
index 0000000..6d9d63a
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -0,0 +1,2975 @@
+/*
+ * Copyright (C) 2006-2015 Tobias Brunner
+ * Copyright (C) 2005-2009 Martin Willi
+ * Copyright (C) 2008-2016 Andreas Steffen
+ * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
+ * Copyright (C) 2006 Daniel Roethlisberger
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.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 <unistd.h>
+#include <time.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include "kernel_netlink_ipsec.h"
+#include "kernel_netlink_shared.h"
+
+#include <daemon.h>
+#include <utils/debug.h>
+#include <threading/mutex.h>
+#include <collections/array.h>
+#include <collections/hashtable.h>
+#include <collections/linked_list.h>
+
+/** Required for Linux 2.6.26 kernel and later */
+#ifndef XFRM_STATE_AF_UNSPEC
+#define XFRM_STATE_AF_UNSPEC 32
+#endif
+
+/** From linux/in.h */
+#ifndef IP_XFRM_POLICY
+#define IP_XFRM_POLICY 17
+#endif
+
+/** Missing on uclibc */
+#ifndef IPV6_XFRM_POLICY
+#define IPV6_XFRM_POLICY 34
+#endif /*IPV6_XFRM_POLICY*/
+
+/* from linux/udp.h */
+#ifndef UDP_ENCAP
+#define UDP_ENCAP 100
+#endif
+
+#ifndef UDP_ENCAP_ESPINUDP
+#define UDP_ENCAP_ESPINUDP 2
+#endif
+
+/* this is not defined on some platforms */
+#ifndef SOL_UDP
+#define SOL_UDP IPPROTO_UDP
+#endif
+
+/** Base priority for installed policies */
+#define PRIO_BASE 384
+
+/** Default lifetime of an acquire XFRM state (in seconds) */
+#define DEFAULT_ACQUIRE_LIFETIME 165
+
+/**
+ * Map the limit for bytes and packets to XFRM_INF by default
+ */
+#define XFRM_LIMIT(x) ((x) == 0 ? XFRM_INF : (x))
+
+/**
+ * Create ORable bitfield of XFRM NL groups
+ */
+#define XFRMNLGRP(x) (1<<(XFRMNLGRP_##x-1))
+
+/**
+ * Returns a pointer to the first rtattr following the nlmsghdr *nlh and the
+ * 'usual' netlink data x like 'struct xfrm_usersa_info'
+ */
+#define XFRM_RTA(nlh, x) ((struct rtattr*)(NLMSG_DATA(nlh) + \
+										   NLMSG_ALIGN(sizeof(x))))
+/**
+ * Returns the total size of attached rta data
+ * (after 'usual' netlink data x like 'struct xfrm_usersa_info')
+ */
+#define XFRM_PAYLOAD(nlh, x) NLMSG_PAYLOAD(nlh, sizeof(x))
+
+typedef struct kernel_algorithm_t kernel_algorithm_t;
+
+/**
+ * Mapping of IKEv2 kernel identifier to linux crypto API names
+ */
+struct kernel_algorithm_t {
+	/**
+	 * Identifier specified in IKEv2
+	 */
+	int ikev2;
+
+	/**
+	 * Name of the algorithm in linux crypto API
+	 */
+	char *name;
+};
+
+ENUM(xfrm_msg_names, XFRM_MSG_NEWSA, XFRM_MSG_MAPPING,
+	"XFRM_MSG_NEWSA",
+	"XFRM_MSG_DELSA",
+	"XFRM_MSG_GETSA",
+	"XFRM_MSG_NEWPOLICY",
+	"XFRM_MSG_DELPOLICY",
+	"XFRM_MSG_GETPOLICY",
+	"XFRM_MSG_ALLOCSPI",
+	"XFRM_MSG_ACQUIRE",
+	"XFRM_MSG_EXPIRE",
+	"XFRM_MSG_UPDPOLICY",
+	"XFRM_MSG_UPDSA",
+	"XFRM_MSG_POLEXPIRE",
+	"XFRM_MSG_FLUSHSA",
+	"XFRM_MSG_FLUSHPOLICY",
+	"XFRM_MSG_NEWAE",
+	"XFRM_MSG_GETAE",
+	"XFRM_MSG_REPORT",
+	"XFRM_MSG_MIGRATE",
+	"XFRM_MSG_NEWSADINFO",
+	"XFRM_MSG_GETSADINFO",
+	"XFRM_MSG_NEWSPDINFO",
+	"XFRM_MSG_GETSPDINFO",
+	"XFRM_MSG_MAPPING"
+);
+
+ENUM(xfrm_attr_type_names, XFRMA_UNSPEC, XFRMA_REPLAY_ESN_VAL,
+	"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",
+	"XFRMA_ALG_AUTH_TRUNC",
+	"XFRMA_MARK",
+	"XFRMA_TFCPAD",
+	"XFRMA_REPLAY_ESN_VAL",
+);
+
+/**
+ * Algorithms for encryption
+ */
+static kernel_algorithm_t encryption_algs[] = {
+/*	{ENCR_DES_IV64,				"***"				}, */
+	{ENCR_DES,					"des"				},
+	{ENCR_3DES,					"des3_ede"			},
+/*	{ENCR_RC5,					"***"				}, */
+/*	{ENCR_IDEA,					"***"				}, */
+	{ENCR_CAST,					"cast5"				},
+	{ENCR_BLOWFISH,				"blowfish"			},
+/*	{ENCR_3IDEA,				"***"				}, */
+/*	{ENCR_DES_IV32,				"***"				}, */
+	{ENCR_NULL,					"cipher_null"		},
+	{ENCR_AES_CBC,				"aes"				},
+	{ENCR_AES_CTR,				"rfc3686(ctr(aes))"	},
+	{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))"	},
+	{ENCR_NULL_AUTH_AES_GMAC,	"rfc4543(gcm(aes))"	},
+	{ENCR_CAMELLIA_CBC,			"cbc(camellia)"		},
+/*	{ENCR_CAMELLIA_CTR,			"***"				}, */
+/*	{ENCR_CAMELLIA_CCM_ICV8,	"***"				}, */
+/*	{ENCR_CAMELLIA_CCM_ICV12,	"***"				}, */
+/*	{ENCR_CAMELLIA_CCM_ICV16,	"***"				}, */
+	{ENCR_SERPENT_CBC,			"serpent"			},
+	{ENCR_TWOFISH_CBC,			"twofish"			},
+	{ENCR_CHACHA20_POLY1305,	"rfc7539esp(chacha20,poly1305)"},
+};
+
+/**
+ * Algorithms for integrity protection
+ */
+static kernel_algorithm_t integrity_algs[] = {
+	{AUTH_HMAC_MD5_96,			"md5"				},
+	{AUTH_HMAC_MD5_128,			"hmac(md5)"			},
+	{AUTH_HMAC_SHA1_96,			"sha1"				},
+	{AUTH_HMAC_SHA1_160,		"hmac(sha1)"		},
+	{AUTH_HMAC_SHA2_256_96,		"sha256"			},
+	{AUTH_HMAC_SHA2_256_128,	"hmac(sha256)"		},
+	{AUTH_HMAC_SHA2_384_192,	"hmac(sha384)"		},
+	{AUTH_HMAC_SHA2_512_256,	"hmac(sha512)"		},
+/*	{AUTH_DES_MAC,				"***"				}, */
+/*	{AUTH_KPDK_MD5,				"***"				}, */
+	{AUTH_AES_XCBC_96,			"xcbc(aes)"			},
+};
+
+/**
+ * Algorithms for IPComp
+ */
+static kernel_algorithm_t compression_algs[] = {
+/*	{IPCOMP_OUI,				"***"				}, */
+	{IPCOMP_DEFLATE,			"deflate"			},
+	{IPCOMP_LZS,				"lzs"				},
+	{IPCOMP_LZJH,				"lzjh"				},
+};
+
+/**
+ * Look up a kernel algorithm name and its key size
+ */
+static char* lookup_algorithm(transform_type_t type, int ikev2)
+{
+	kernel_algorithm_t *list;
+	int i, count;
+	char *name;
+
+	switch (type)
+	{
+		case ENCRYPTION_ALGORITHM:
+			list = encryption_algs;
+			count = countof(encryption_algs);
+			break;
+		case INTEGRITY_ALGORITHM:
+			list = integrity_algs;
+			count = countof(integrity_algs);
+			break;
+		case COMPRESSION_ALGORITHM:
+			list = compression_algs;
+			count = countof(compression_algs);
+			break;
+		default:
+			return NULL;
+	}
+	for (i = 0; i < count; i++)
+	{
+		if (list[i].ikev2 == ikev2)
+		{
+			return list[i].name;
+		}
+	}
+	if (charon->kernel->lookup_algorithm(charon->kernel, ikev2, type, NULL,
+										 &name))
+	{
+		return name;
+	}
+	return NULL;
+}
+
+typedef struct private_kernel_netlink_ipsec_t private_kernel_netlink_ipsec_t;
+
+/**
+ * Private variables and functions of kernel_netlink class.
+ */
+struct private_kernel_netlink_ipsec_t {
+	/**
+	 * Public part of the kernel_netlink_t object
+	 */
+	kernel_netlink_ipsec_t public;
+
+	/**
+	 * Mutex to lock access to installed policies
+	 */
+	mutex_t *mutex;
+
+	/**
+	 * Hash table of installed policies (policy_entry_t)
+	 */
+	hashtable_t *policies;
+
+	/**
+	 * Hash table of IPsec SAs using policies (ipsec_sa_t)
+	 */
+	hashtable_t *sas;
+
+	/**
+	 * Netlink xfrm socket (IPsec)
+	 */
+	netlink_socket_t *socket_xfrm;
+
+	/**
+	 * Netlink xfrm socket to receive acquire and expire events
+	 */
+	int socket_xfrm_events;
+
+	/**
+	 * Whether to install routes along policies
+	 */
+	bool install_routes;
+
+	/**
+	 * Whether to set protocol and ports on selector installed with transport
+	 * mode IPsec SAs
+	 */
+	bool proto_port_transport;
+
+	/**
+	 * Whether to always use UPDATE to install policies
+	 */
+	bool policy_update;
+
+	/**
+	 * Installed port based IKE bypass policies, as bypass_t
+	 */
+	array_t *bypass;
+};
+
+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 a route_entry_t object
+ */
+static void route_entry_destroy(route_entry_t *this)
+{
+	free(this->if_name);
+	this->src_ip->destroy(this->src_ip);
+	DESTROY_IF(this->gateway);
+	chunk_free(&this->dst_net);
+	free(this);
+}
+
+/**
+ * Compare two route_entry_t objects
+ */
+static bool route_entry_equals(route_entry_t *a, route_entry_t *b)
+{
+	return a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
+		   a->src_ip->ip_equals(a->src_ip, b->src_ip) &&
+		   a->gateway->ip_equals(a->gateway, b->gateway) &&
+		   chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen;
+}
+
+typedef struct ipsec_sa_t ipsec_sa_t;
+
+/**
+ * IPsec SA assigned to a policy.
+ */
+struct ipsec_sa_t {
+	/** Source address of this SA */
+	host_t *src;
+
+	/** Destination address of this SA */
+	host_t *dst;
+
+	/** Optional mark */
+	mark_t mark;
+
+	/** Description of this SA */
+	ipsec_sa_cfg_t cfg;
+
+	/** Reference count for this SA */
+	refcount_t refcount;
+};
+
+/**
+ * Hash function for ipsec_sa_t objects
+ */
+static u_int ipsec_sa_hash(ipsec_sa_t *sa)
+{
+	return chunk_hash_inc(sa->src->get_address(sa->src),
+						  chunk_hash_inc(sa->dst->get_address(sa->dst),
+						  chunk_hash_inc(chunk_from_thing(sa->mark),
+						  chunk_hash(chunk_from_thing(sa->cfg)))));
+}
+
+/**
+ * Equality function for ipsec_sa_t objects
+ */
+static bool ipsec_sa_equals(ipsec_sa_t *sa, ipsec_sa_t *other_sa)
+{
+	return sa->src->ip_equals(sa->src, other_sa->src) &&
+		   sa->dst->ip_equals(sa->dst, other_sa->dst) &&
+		   memeq(&sa->mark, &other_sa->mark, sizeof(mark_t)) &&
+		   memeq(&sa->cfg, &other_sa->cfg, sizeof(ipsec_sa_cfg_t));
+}
+
+/**
+ * Allocate or reference an IPsec SA object
+ */
+static ipsec_sa_t *ipsec_sa_create(private_kernel_netlink_ipsec_t *this,
+								   host_t *src, host_t *dst, mark_t mark,
+								   ipsec_sa_cfg_t *cfg)
+{
+	ipsec_sa_t *sa, *found;
+	INIT(sa,
+		.src = src,
+		.dst = dst,
+		.mark = mark,
+		.cfg = *cfg,
+	);
+	found = this->sas->get(this->sas, sa);
+	if (!found)
+	{
+		sa->src = src->clone(src);
+		sa->dst = dst->clone(dst);
+		this->sas->put(this->sas, sa, sa);
+	}
+	else
+	{
+		free(sa);
+		sa = found;
+	}
+	ref_get(&sa->refcount);
+	return sa;
+}
+
+/**
+ * Release and destroy an IPsec SA object
+ */
+static void ipsec_sa_destroy(private_kernel_netlink_ipsec_t *this,
+							 ipsec_sa_t *sa)
+{
+	if (ref_put(&sa->refcount))
+	{
+		this->sas->remove(this->sas, sa);
+		DESTROY_IF(sa->src);
+		DESTROY_IF(sa->dst);
+		free(sa);
+	}
+}
+
+typedef struct policy_sa_t policy_sa_t;
+typedef struct policy_sa_fwd_t policy_sa_fwd_t;
+
+/**
+ * Mapping between a policy and an IPsec SA.
+ */
+struct policy_sa_t {
+	/** Priority assigned to the policy when installed with this SA */
+	u_int32_t priority;
+
+	/** Type of the policy */
+	policy_type_t type;
+
+	/** Assigned SA */
+	ipsec_sa_t *sa;
+};
+
+/**
+ * For forward policies we also cache the traffic selectors in order to install
+ * the route.
+ */
+struct policy_sa_fwd_t {
+	/** Generic interface */
+	policy_sa_t generic;
+
+	/** Source traffic selector of this policy */
+	traffic_selector_t *src_ts;
+
+	/** Destination traffic selector of this policy */
+	traffic_selector_t *dst_ts;
+};
+
+/**
+ * Create a policy_sa(_fwd)_t object
+ */
+static policy_sa_t *policy_sa_create(private_kernel_netlink_ipsec_t *this,
+	policy_dir_t dir, policy_type_t type, host_t *src, host_t *dst,
+	traffic_selector_t *src_ts, traffic_selector_t *dst_ts, mark_t mark,
+	ipsec_sa_cfg_t *cfg)
+{
+	policy_sa_t *policy;
+
+	if (dir == POLICY_FWD)
+	{
+		policy_sa_fwd_t *fwd;
+		INIT(fwd,
+			.src_ts = src_ts->clone(src_ts),
+			.dst_ts = dst_ts->clone(dst_ts),
+		);
+		policy = &fwd->generic;
+	}
+	else
+	{
+		INIT(policy, .priority = 0);
+	}
+	policy->type = type;
+	policy->sa = ipsec_sa_create(this, src, dst, mark, cfg);
+	return policy;
+}
+
+/**
+ * Destroy a policy_sa(_fwd)_t object
+ */
+static void policy_sa_destroy(policy_sa_t *policy, policy_dir_t *dir,
+							  private_kernel_netlink_ipsec_t *this)
+{
+	if (*dir == POLICY_FWD)
+	{
+		policy_sa_fwd_t *fwd = (policy_sa_fwd_t*)policy;
+		fwd->src_ts->destroy(fwd->src_ts);
+		fwd->dst_ts->destroy(fwd->dst_ts);
+	}
+	ipsec_sa_destroy(this, policy->sa);
+	free(policy);
+}
+
+typedef struct policy_entry_t policy_entry_t;
+
+/**
+ * Installed kernel policy.
+ */
+struct policy_entry_t {
+
+	/** Direction of this policy: in, out, forward */
+	u_int8_t direction;
+
+	/** Parameters of installed policy */
+	struct xfrm_selector sel;
+
+	/** Optional mark */
+	u_int32_t mark;
+
+	/** Associated route installed for this policy */
+	route_entry_t *route;
+
+	/** List of SAs this policy is used by, ordered by priority */
+	linked_list_t *used_by;
+
+	/** reqid for this policy */
+	u_int32_t reqid;
+};
+
+/**
+ * Destroy a policy_entry_t object
+ */
+static void policy_entry_destroy(private_kernel_netlink_ipsec_t *this,
+								 policy_entry_t *policy)
+{
+	if (policy->route)
+	{
+		route_entry_destroy(policy->route);
+	}
+	if (policy->used_by)
+	{
+		policy->used_by->invoke_function(policy->used_by,
+										(linked_list_invoke_t)policy_sa_destroy,
+										 &policy->direction, this);
+		policy->used_by->destroy(policy->used_by);
+	}
+	free(policy);
+}
+
+/**
+ * Hash function for policy_entry_t objects
+ */
+static u_int policy_hash(policy_entry_t *key)
+{
+	chunk_t chunk = chunk_from_thing(key->sel);
+	return chunk_hash_inc(chunk, chunk_hash(chunk_from_thing(key->mark)));
+}
+
+/**
+ * Equality function for policy_entry_t objects
+ */
+static bool policy_equals(policy_entry_t *key, policy_entry_t *other_key)
+{
+	return memeq(&key->sel, &other_key->sel, sizeof(struct xfrm_selector)) &&
+		   key->mark == other_key->mark &&
+		   key->direction == other_key->direction;
+}
+
+/**
+ * Calculate the priority of a policy
+ */
+static inline u_int32_t get_priority(policy_entry_t *policy,
+									 policy_priority_t prio)
+{
+	u_int32_t priority = PRIO_BASE;
+	switch (prio)
+	{
+		case POLICY_PRIORITY_FALLBACK:
+			priority <<= 1;
+			/* fall-through */
+		case POLICY_PRIORITY_ROUTED:
+			priority <<= 1;
+			/* fall-through */
+		case POLICY_PRIORITY_DEFAULT:
+			priority <<= 1;
+			/* fall-through */
+		case POLICY_PRIORITY_PASS:
+			break;
+	}
+	/* calculate priority based on selector size, small size = high prio */
+	priority -= policy->sel.prefixlen_s;
+	priority -= policy->sel.prefixlen_d;
+	priority <<= 2; /* make some room for the two flags */
+	priority += policy->sel.sport_mask || policy->sel.dport_mask ? 0 : 2;
+	priority += policy->sel.proto ? 0 : 1;
+	return priority;
+}
+
+/**
+ * Convert the general ipsec mode to the one defined in xfrm.h
+ */
+static u_int8_t mode2kernel(ipsec_mode_t mode)
+{
+	switch (mode)
+	{
+		case MODE_TRANSPORT:
+			return XFRM_MODE_TRANSPORT;
+		case MODE_TUNNEL:
+			return XFRM_MODE_TUNNEL;
+		case MODE_BEET:
+			return XFRM_MODE_BEET;
+		default:
+			return mode;
+	}
+}
+
+/**
+ * Convert a host_t to a struct xfrm_address
+ */
+static void host2xfrm(host_t *host, xfrm_address_t *xfrm)
+{
+	chunk_t chunk = host->get_address(host);
+	memcpy(xfrm, chunk.ptr, min(chunk.len, sizeof(xfrm_address_t)));
+}
+
+/**
+ * Convert a struct xfrm_address to a host_t
+ */
+static host_t* xfrm2host(int family, xfrm_address_t *xfrm, u_int16_t port)
+{
+	chunk_t chunk;
+
+	switch (family)
+	{
+		case AF_INET:
+			chunk = chunk_create((u_char*)&xfrm->a4, sizeof(xfrm->a4));
+			break;
+		case AF_INET6:
+			chunk = chunk_create((u_char*)&xfrm->a6, sizeof(xfrm->a6));
+			break;
+		default:
+			return NULL;
+	}
+	return host_create_from_chunk(family, chunk, ntohs(port));
+}
+
+/**
+ * Convert a traffic selector address range to subnet and its mask.
+ */
+static void ts2subnet(traffic_selector_t* ts,
+					  xfrm_address_t *net, u_int8_t *mask)
+{
+	host_t *net_host;
+	chunk_t net_chunk;
+
+	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);
+}
+
+/**
+ * Convert a traffic selector port range to port/portmask
+ */
+static void ts2ports(traffic_selector_t* ts,
+					 u_int16_t *port, u_int16_t *mask)
+{
+	uint16_t from, to, bitmask;
+	int bit;
+
+	from = ts->get_from_port(ts);
+	to = ts->get_to_port(ts);
+
+	/* Quick check for a single port */
+	if (from == to)
+	{
+		*port = htons(from);
+		*mask = ~0;
+	}
+	else
+	{
+		/* Compute the port mask for port ranges */
+		*mask = 0;
+
+		for (bit = 15; bit >= 0; bit--)
+		{
+			bitmask = 1 << bit;
+
+			if ((bitmask & from) != (bitmask & to))
+			{
+				*port = htons(from & *mask);
+				*mask = htons(*mask);
+				return;
+			}
+			*mask |= bitmask;
+		}
+	}
+	return;
+}
+
+/**
+ * Convert a pair of traffic_selectors to an xfrm_selector
+ */
+static struct xfrm_selector ts2selector(traffic_selector_t *src,
+										traffic_selector_t *dst)
+{
+	struct xfrm_selector sel;
+	u_int16_t port;
+
+	memset(&sel, 0, sizeof(sel));
+	sel.family = (src->get_type(src) == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6;
+	/* src or dest proto may be "any" (0), use more restrictive one */
+	sel.proto = max(src->get_protocol(src), dst->get_protocol(dst));
+	ts2subnet(dst, &sel.daddr, &sel.prefixlen_d);
+	ts2subnet(src, &sel.saddr, &sel.prefixlen_s);
+	ts2ports(dst, &sel.dport, &sel.dport_mask);
+	ts2ports(src, &sel.sport, &sel.sport_mask);
+	if ((sel.proto == IPPROTO_ICMP || sel.proto == IPPROTO_ICMPV6) &&
+		(sel.dport || sel.sport))
+	{
+		/* the kernel expects the ICMP type and code in the source and
+		 * destination port fields, respectively. */
+		port = ntohs(max(sel.dport, sel.sport));
+		sel.sport = htons(traffic_selector_icmp_type(port));
+		sel.sport_mask = sel.sport ? ~0 : 0;
+		sel.dport = htons(traffic_selector_icmp_code(port));
+		sel.dport_mask = sel.dport ? ~0 : 0;
+	}
+	sel.ifindex = 0;
+	sel.user = 0;
+
+	return sel;
+}
+
+/**
+ * Convert an xfrm_selector to a src|dst traffic_selector
+ */
+static traffic_selector_t* selector2ts(struct xfrm_selector *sel, bool src)
+{
+	u_char *addr;
+	u_int8_t prefixlen;
+	u_int16_t port = 0;
+	host_t *host = NULL;
+
+	if (src)
+	{
+		addr = (u_char*)&sel->saddr;
+		prefixlen = sel->prefixlen_s;
+		if (sel->sport_mask)
+		{
+			port = ntohs(sel->sport);
+		}
+	}
+	else
+	{
+		addr = (u_char*)&sel->daddr;
+		prefixlen = sel->prefixlen_d;
+		if (sel->dport_mask)
+		{
+			port = ntohs(sel->dport);
+		}
+	}
+	if (sel->proto == IPPROTO_ICMP || sel->proto == IPPROTO_ICMPV6)
+	{	/* convert ICMP[v6] message type and code as supplied by the kernel in
+		 * source and destination ports (both in network order) */
+		port = (sel->sport >> 8) | (sel->dport & 0xff00);
+		port = ntohs(port);
+	}
+	/* 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)
+	{
+		host = host_create_from_chunk(AF_INET, chunk_create(addr, 4), 0);
+	}
+	else if (sel->family == AF_INET6 || sel->prefixlen_s == 128)
+	{
+		host = host_create_from_chunk(AF_INET6, chunk_create(addr, 16), 0);
+	}
+
+	if (host)
+	{
+		return traffic_selector_create_from_subnet(host, prefixlen,
+											sel->proto, port, port ?: 65535);
+	}
+	return NULL;
+}
+
+/**
+ * Process a XFRM_MSG_ACQUIRE from kernel
+ */
+static void process_acquire(private_kernel_netlink_ipsec_t *this,
+							struct nlmsghdr *hdr)
+{
+	struct xfrm_user_acquire *acquire;
+	struct rtattr *rta;
+	size_t rtasize;
+	traffic_selector_t *src_ts, *dst_ts;
+	u_int32_t reqid = 0;
+	int proto = 0;
+
+	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))
+	{
+		DBG2(DBG_KNL, "  %N", xfrm_attr_type_names, rta->rta_type);
+
+		if (rta->rta_type == XFRMA_TMPL)
+		{
+			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)
+	{
+		case 0:
+		case IPPROTO_ESP:
+		case IPPROTO_AH:
+			break;
+		default:
+			/* acquire for AH/ESP only, not for IPCOMP */
+			return;
+	}
+	src_ts = selector2ts(&acquire->sel, TRUE);
+	dst_ts = selector2ts(&acquire->sel, FALSE);
+
+	charon->kernel->acquire(charon->kernel, reqid, src_ts, dst_ts);
+}
+
+/**
+ * Process a XFRM_MSG_EXPIRE from kernel
+ */
+static void process_expire(private_kernel_netlink_ipsec_t *this,
+						   struct nlmsghdr *hdr)
+{
+	struct xfrm_user_expire *expire;
+	u_int32_t spi;
+	u_int8_t protocol;
+	host_t *dst;
+
+	expire = NLMSG_DATA(hdr);
+	protocol = expire->state.id.proto;
+	spi = expire->state.id.spi;
+
+	DBG2(DBG_KNL, "received a XFRM_MSG_EXPIRE");
+
+	if (protocol == IPPROTO_ESP || protocol == IPPROTO_AH)
+	{
+		dst = xfrm2host(expire->state.family, &expire->state.id.daddr, 0);
+		if (dst)
+		{
+			charon->kernel->expire(charon->kernel, protocol, spi, dst,
+								   expire->hard != 0);
+			dst->destroy(dst);
+		}
+	}
+}
+
+/**
+ * Process a XFRM_MSG_MIGRATE from kernel
+ */
+static void process_migrate(private_kernel_netlink_ipsec_t *this,
+							struct nlmsghdr *hdr)
+{
+	struct xfrm_userpolicy_id *policy_id;
+	struct rtattr *rta;
+	size_t rtasize;
+	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;
+	u_int32_t reqid = 0;
+	policy_dir_t dir;
+
+	policy_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;
+
+			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);
+			reqid = migrate->reqid;
+			DBG2(DBG_KNL, "  migrate %H...%H to %H...%H, reqid {%u}",
+						   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)
+	{
+		charon->kernel->migrate(charon->kernel, reqid, src_ts, dst_ts, dir,
+								local, remote);
+	}
+	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,
+							struct nlmsghdr *hdr)
+{
+	struct xfrm_user_mapping *mapping;
+	u_int32_t spi;
+
+	mapping = NLMSG_DATA(hdr);
+	spi = mapping->id.spi;
+
+	DBG2(DBG_KNL, "received a XFRM_MSG_MAPPING");
+
+	if (mapping->id.proto == IPPROTO_ESP)
+	{
+		host_t *dst, *new;
+
+		dst = xfrm2host(mapping->id.family, &mapping->id.daddr, 0);
+		if (dst)
+		{
+			new = xfrm2host(mapping->id.family, &mapping->new_saddr,
+							mapping->new_sport);
+			if (new)
+			{
+				charon->kernel->mapping(charon->kernel, IPPROTO_ESP, spi, dst,
+										new);
+				new->destroy(new);
+			}
+			dst->destroy(dst);
+		}
+	}
+}
+
+/**
+ * Receives events from kernel
+ */
+static bool receive_events(private_kernel_netlink_ipsec_t *this, int fd,
+						   watcher_event_t event)
+{
+	char response[1024];
+	struct nlmsghdr *hdr = (struct nlmsghdr*)response;
+	struct sockaddr_nl addr;
+	socklen_t addr_len = sizeof(addr);
+	int len;
+
+	len = recvfrom(this->socket_xfrm_events, response, sizeof(response),
+				   MSG_DONTWAIT, (struct sockaddr*)&addr, &addr_len);
+	if (len < 0)
+	{
+		switch (errno)
+		{
+			case EINTR:
+				/* interrupted, try again */
+				return TRUE;
+			case EAGAIN:
+				/* no data ready, select again */
+				return TRUE;
+			default:
+				DBG1(DBG_KNL, "unable to receive from xfrm event socket");
+				sleep(1);
+				return TRUE;
+		}
+	}
+
+	if (addr.nl_pid != 0)
+	{	/* not from kernel. not interested, try another one */
+		return TRUE;
+	}
+
+	while (NLMSG_OK(hdr, len))
+	{
+		switch (hdr->nlmsg_type)
+		{
+			case XFRM_MSG_ACQUIRE:
+				process_acquire(this, hdr);
+				break;
+			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;
+			default:
+				DBG1(DBG_KNL, "received unknown event from xfrm event "
+							  "socket: %d", hdr->nlmsg_type);
+				break;
+		}
+		hdr = NLMSG_NEXT(hdr, len);
+	}
+	return TRUE;
+}
+
+METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
+	private_kernel_netlink_ipsec_t *this)
+{
+	return KERNEL_ESP_V3_TFC;
+}
+
+/**
+ * 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 *spi)
+{
+	netlink_buf_t request;
+	struct nlmsghdr *hdr, *out;
+	struct xfrm_userspi_info *userspi;
+	u_int32_t received_spi = 0;
+	size_t len;
+
+	memset(&request, 0, sizeof(request));
+
+	hdr = &request.hdr;
+	hdr->nlmsg_flags = NLM_F_REQUEST;
+	hdr->nlmsg_type = XFRM_MSG_ALLOCSPI;
+	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userspi_info));
+
+	userspi = NLMSG_DATA(hdr);
+	host2xfrm(src, &userspi->info.saddr);
+	host2xfrm(dst, &userspi->info.id.daddr);
+	userspi->info.id.proto = proto;
+	userspi->info.mode = XFRM_MODE_TUNNEL;
+	userspi->info.family = src->get_family(src);
+	userspi->min = min;
+	userspi->max = max;
+
+	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:
+				{
+					struct xfrm_usersa_info* usersa = NLMSG_DATA(hdr);
+					received_spi = usersa->id.spi;
+					break;
+				}
+				case NLMSG_ERROR:
+				{
+					struct nlmsgerr *err = NLMSG_DATA(hdr);
+					DBG1(DBG_KNL, "allocating SPI failed: %s (%d)",
+						 strerror(-err->error), -err->error);
+					break;
+				}
+				default:
+					hdr = NLMSG_NEXT(hdr, len);
+					continue;
+				case NLMSG_DONE:
+					break;
+			}
+			break;
+		}
+		free(out);
+	}
+
+	if (received_spi == 0)
+	{
+		return FAILED;
+	}
+
+	*spi = received_spi;
+	return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, get_spi, status_t,
+	private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
+	u_int8_t protocol, u_int32_t *spi)
+{
+	if (get_spi_internal(this, src, dst, protocol,
+						 0xc0000000, 0xcFFFFFFF, spi) != SUCCESS)
+	{
+		DBG1(DBG_KNL, "unable to get SPI");
+		return FAILED;
+	}
+
+	DBG2(DBG_KNL, "got SPI %.8x", ntohl(*spi));
+	return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, get_cpi, status_t,
+	private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
+	u_int16_t *cpi)
+{
+	u_int32_t received_spi = 0;
+
+	if (get_spi_internal(this, src, dst, IPPROTO_COMP,
+						 0x100, 0xEFFF, &received_spi) != SUCCESS)
+	{
+		DBG1(DBG_KNL, "unable to get CPI");
+		return FAILED;
+	}
+
+	*cpi = htons((u_int16_t)ntohl(received_spi));
+
+	DBG2(DBG_KNL, "got CPI %.4x", ntohs(*cpi));
+	return SUCCESS;
+}
+
+/**
+ * Add a XFRM mark to message if required
+ */
+static bool add_mark(struct nlmsghdr *hdr, int buflen, mark_t mark)
+{
+	if (mark.value)
+	{
+		struct xfrm_mark *xmrk;
+
+		xmrk = netlink_reserve(hdr, buflen, XFRMA_MARK, sizeof(*xmrk));
+		if (!xmrk)
+		{
+			return FALSE;
+		}
+		xmrk->v = mark.value;
+		xmrk->m = mark.mask;
+	}
+	return TRUE;
+}
+
+METHOD(kernel_ipsec_t, add_sa, status_t,
+	private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
+	u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
+	u_int32_t tfc, lifetime_cfg_t *lifetime, 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, u_int32_t replay_window,
+	bool initiator, bool encap, bool esn, bool inbound, bool update,
+	linked_list_t* src_ts, linked_list_t* dst_ts)
+{
+	netlink_buf_t request;
+	char *alg_name;
+	struct nlmsghdr *hdr;
+	struct xfrm_usersa_info *sa;
+	u_int16_t icv_size = 64;
+	ipsec_mode_t original_mode = mode;
+	traffic_selector_t *first_src_ts, *first_dst_ts;
+	status_t status = FAILED;
+
+	/* 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)
+	{
+		lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}};
+		add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark,
+			   tfc, &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED,
+			   chunk_empty, mode, ipcomp, 0, 0, initiator, FALSE, FALSE,
+			   inbound, update, src_ts, dst_ts);
+		ipcomp = IPCOMP_NONE;
+		/* use transport mode ESP SA, IPComp uses tunnel mode */
+		mode = MODE_TRANSPORT;
+	}
+
+	memset(&request, 0, sizeof(request));
+
+	DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}  (mark "
+				  "%u/0x%08x)", ntohl(spi), reqid, mark.value, mark.mask);
+
+	hdr = &request.hdr;
+	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+	hdr->nlmsg_type = update ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
+	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
+
+	sa = NLMSG_DATA(hdr);
+	host2xfrm(src, &sa->saddr);
+	host2xfrm(dst, &sa->id.daddr);
+	sa->id.spi = spi;
+	sa->id.proto = protocol;
+	sa->family = src->get_family(src);
+	sa->mode = mode2kernel(mode);
+	switch (mode)
+	{
+		case MODE_TUNNEL:
+			sa->flags |= XFRM_STATE_AF_UNSPEC;
+			break;
+		case MODE_BEET:
+		case MODE_TRANSPORT:
+			if (original_mode == MODE_TUNNEL)
+			{	/* don't install selectors for switched SAs.  because only one
+				 * selector can be installed other traffic would get dropped */
+				break;
+			}
+			if (src_ts->get_first(src_ts, (void**)&first_src_ts) == SUCCESS &&
+				dst_ts->get_first(dst_ts, (void**)&first_dst_ts) == SUCCESS)
+			{
+				sa->sel = ts2selector(first_src_ts, first_dst_ts);
+				if (!this->proto_port_transport)
+				{
+					/* don't install proto/port on SA. This would break
+					 * potential secondary SAs for the same address using a
+					 * different prot/port. */
+					sa->sel.proto = 0;
+					sa->sel.dport = sa->sel.dport_mask = 0;
+					sa->sel.sport = sa->sel.sport_mask = 0;
+				}
+			}
+			break;
+		default:
+			break;
+	}
+
+	sa->reqid = reqid;
+	sa->lft.soft_byte_limit = XFRM_LIMIT(lifetime->bytes.rekey);
+	sa->lft.hard_byte_limit = XFRM_LIMIT(lifetime->bytes.life);
+	sa->lft.soft_packet_limit = XFRM_LIMIT(lifetime->packets.rekey);
+	sa->lft.hard_packet_limit = XFRM_LIMIT(lifetime->packets.life);
+	/* we use lifetimes since added, not since used */
+	sa->lft.soft_add_expires_seconds = lifetime->time.rekey;
+	sa->lft.hard_add_expires_seconds = lifetime->time.life;
+	sa->lft.soft_use_expires_seconds = 0;
+	sa->lft.hard_use_expires_seconds = 0;
+
+	switch (enc_alg)
+	{
+		case ENCR_UNDEFINED:
+			/* no encryption */
+			break;
+		case ENCR_AES_CCM_ICV16:
+		case ENCR_AES_GCM_ICV16:
+		case ENCR_NULL_AUTH_AES_GMAC:
+		case ENCR_CAMELLIA_CCM_ICV16:
+		case ENCR_CHACHA20_POLY1305:
+			icv_size += 32;
+			/* FALL */
+		case ENCR_AES_CCM_ICV12:
+		case ENCR_AES_GCM_ICV12:
+		case ENCR_CAMELLIA_CCM_ICV12:
+			icv_size += 32;
+			/* FALL */
+		case ENCR_AES_CCM_ICV8:
+		case ENCR_AES_GCM_ICV8:
+		case ENCR_CAMELLIA_CCM_ICV8:
+		{
+			struct xfrm_algo_aead *algo;
+
+			alg_name = lookup_algorithm(ENCRYPTION_ALGORITHM, enc_alg);
+			if (alg_name == NULL)
+			{
+				DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
+						 encryption_algorithm_names, enc_alg);
+					goto failed;
+			}
+			DBG2(DBG_KNL, "  using encryption algorithm %N with key size %d",
+				 encryption_algorithm_names, enc_alg, enc_key.len * 8);
+
+			algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AEAD,
+								   sizeof(*algo) + enc_key.len);
+			if (!algo)
+			{
+				goto failed;
+			}
+			algo->alg_key_len = enc_key.len * 8;
+			algo->alg_icv_len = icv_size;
+			strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
+			algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
+			memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
+			break;
+		}
+		default:
+		{
+			struct xfrm_algo *algo;
+
+			alg_name = lookup_algorithm(ENCRYPTION_ALGORITHM, enc_alg);
+			if (alg_name == NULL)
+			{
+				DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
+					 encryption_algorithm_names, enc_alg);
+				goto failed;
+			}
+			DBG2(DBG_KNL, "  using encryption algorithm %N with key size %d",
+				 encryption_algorithm_names, enc_alg, enc_key.len * 8);
+
+			algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_CRYPT,
+								   sizeof(*algo) + enc_key.len);
+			if (!algo)
+			{
+				goto failed;
+			}
+			algo->alg_key_len = enc_key.len * 8;
+			strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
+			algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
+			memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
+		}
+	}
+
+	if (int_alg != AUTH_UNDEFINED)
+	{
+		u_int trunc_len = 0;
+
+		alg_name = lookup_algorithm(INTEGRITY_ALGORITHM, int_alg);
+		if (alg_name == NULL)
+		{
+			DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
+				 integrity_algorithm_names, int_alg);
+			goto failed;
+		}
+		DBG2(DBG_KNL, "  using integrity algorithm %N with key size %d",
+			 integrity_algorithm_names, int_alg, int_key.len * 8);
+
+		switch (int_alg)
+		{
+			case AUTH_HMAC_MD5_128:
+			case AUTH_HMAC_SHA2_256_128:
+				trunc_len = 128;
+				break;
+			case AUTH_HMAC_SHA1_160:
+				trunc_len = 160;
+				break;
+			default:
+				break;
+		}
+
+		if (trunc_len)
+		{
+			struct xfrm_algo_auth* algo;
+
+			/* the kernel uses SHA256 with 96 bit truncation by default,
+			 * use specified truncation size supported by newer kernels.
+			 * also use this for untruncated MD5 and SHA1. */
+			algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AUTH_TRUNC,
+								   sizeof(*algo) + int_key.len);
+			if (!algo)
+			{
+				goto failed;
+			}
+			algo->alg_key_len = int_key.len * 8;
+			algo->alg_trunc_len = trunc_len;
+			strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
+			algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
+			memcpy(algo->alg_key, int_key.ptr, int_key.len);
+		}
+		else
+		{
+			struct xfrm_algo* algo;
+
+			algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AUTH,
+								   sizeof(*algo) + int_key.len);
+			if (!algo)
+			{
+				goto failed;
+			}
+			algo->alg_key_len = int_key.len * 8;
+			strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
+			algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
+			memcpy(algo->alg_key, int_key.ptr, int_key.len);
+		}
+	}
+
+	if (ipcomp != IPCOMP_NONE)
+	{
+		struct xfrm_algo* algo;
+
+		alg_name = lookup_algorithm(COMPRESSION_ALGORITHM, ipcomp);
+		if (alg_name == NULL)
+		{
+			DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
+				 ipcomp_transform_names, ipcomp);
+			goto failed;
+		}
+		DBG2(DBG_KNL, "  using compression algorithm %N",
+			 ipcomp_transform_names, ipcomp);
+
+		algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_COMP,
+							   sizeof(*algo));
+		if (!algo)
+		{
+			goto failed;
+		}
+		algo->alg_key_len = 0;
+		strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
+		algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
+	}
+
+	if (encap)
+	{
+		struct xfrm_encap_tmpl *tmpl;
+
+		tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP, sizeof(*tmpl));
+		if (!tmpl)
+		{
+			goto failed;
+		}
+		tmpl->encap_type = UDP_ENCAP_ESPINUDP;
+		tmpl->encap_sport = htons(src->get_port(src));
+		tmpl->encap_dport = htons(dst->get_port(dst));
+		memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t));
+		/* encap_oa could probably be derived from the
+		 * traffic selectors [rfc4306, p39]. In the netlink kernel
+		 * implementation pluto does the same as we do here but it uses
+		 * encap_oa in the pfkey implementation.
+		 * BUT as /usr/src/linux/net/key/af_key.c indicates the kernel ignores
+		 * it anyway
+		 *   -> does that mean that NAT-T encap doesn't work in transport mode?
+		 * No. The reason the kernel ignores NAT-OA is that it recomputes
+		 * (or, rather, just ignores) the checksum. If packets pass the IPsec
+		 * checks it marks them "checksum ok" so OA isn't needed. */
+	}
+
+	if (!add_mark(hdr, sizeof(request), mark))
+	{
+		goto failed;
+	}
+
+	if (tfc && protocol == IPPROTO_ESP && mode == MODE_TUNNEL)
+	{	/* the kernel supports TFC padding only for tunnel mode ESP SAs */
+		u_int32_t *tfcpad;
+
+		tfcpad = netlink_reserve(hdr, sizeof(request), XFRMA_TFCPAD,
+								 sizeof(*tfcpad));
+		if (!tfcpad)
+		{
+			goto failed;
+		}
+		*tfcpad = tfc;
+	}
+
+	if (protocol != IPPROTO_COMP)
+	{
+		if (replay_window != 0 && (esn || replay_window > 32))
+		{
+			/* for ESN or larger replay windows we need the new
+			 * XFRMA_REPLAY_ESN_VAL attribute to configure a bitmap */
+			struct xfrm_replay_state_esn *replay;
+			u_int32_t bmp_size;
+
+			bmp_size = round_up(replay_window, sizeof(u_int32_t) * 8) / 8;
+			replay = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_ESN_VAL,
+									 sizeof(*replay) + bmp_size);
+			if (!replay)
+			{
+				goto failed;
+			}
+			/* bmp_len contains number uf __u32's */
+			replay->bmp_len = bmp_size / sizeof(u_int32_t);
+			replay->replay_window = replay_window;
+			DBG2(DBG_KNL, "  using replay window of %u packets", replay_window);
+
+			if (esn)
+			{
+				DBG2(DBG_KNL, "  using extended sequence numbers (ESN)");
+				sa->flags |= XFRM_STATE_ESN;
+			}
+		}
+		else
+		{
+			DBG2(DBG_KNL, "  using replay window of %u packets", replay_window);
+			sa->replay_window = replay_window;
+		}
+	}
+
+	if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
+	{
+		if (mark.value)
+		{
+			DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x  "
+						  "(mark %u/0x%08x)", ntohl(spi), mark.value, mark.mask);
+		}
+		else
+		{
+			DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
+		}
+		goto failed;
+	}
+
+	status = SUCCESS;
+
+failed:
+	memwipe(&request, sizeof(request));
+	return status;
+}
+
+/**
+ * Get the ESN replay state (i.e. sequence numbers) of an SA.
+ *
+ * Allocates into one the replay state structure we get from the kernel.
+ */
+static void get_replay_state(private_kernel_netlink_ipsec_t *this,
+							 u_int32_t spi, u_int8_t protocol,
+							 host_t *dst, mark_t mark,
+							 struct xfrm_replay_state_esn **replay_esn,
+							 u_int32_t *replay_esn_len,
+							 struct xfrm_replay_state **replay,
+							 struct xfrm_lifetime_cur **lifetime)
+{
+	netlink_buf_t request;
+	struct nlmsghdr *hdr, *out = NULL;
+	struct xfrm_aevent_id *out_aevent = NULL, *aevent_id;
+	size_t len;
+	struct rtattr *rta;
+	size_t rtasize;
+
+	memset(&request, 0, sizeof(request));
+
+	DBG2(DBG_KNL, "querying replay state from SAD entry with SPI %.8x",
+				   ntohl(spi));
+
+	hdr = &request.hdr;
+	hdr->nlmsg_flags = NLM_F_REQUEST;
+	hdr->nlmsg_type = XFRM_MSG_GETAE;
+	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id));
+
+	aevent_id = NLMSG_DATA(hdr);
+	aevent_id->flags = XFRM_AE_RVAL;
+
+	host2xfrm(dst, &aevent_id->sa_id.daddr);
+	aevent_id->sa_id.spi = spi;
+	aevent_id->sa_id.proto = protocol;
+	aevent_id->sa_id.family = dst->get_family(dst);
+
+	if (!add_mark(hdr, sizeof(request), mark))
+	{
+		return;
+	}
+
+	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_NEWAE:
+				{
+					out_aevent = NLMSG_DATA(hdr);
+					break;
+				}
+				case NLMSG_ERROR:
+				{
+					struct nlmsgerr *err = NLMSG_DATA(hdr);
+					DBG1(DBG_KNL, "querying replay state from SAD entry "
+								  "failed: %s (%d)", strerror(-err->error),
+								  -err->error);
+					break;
+				}
+				default:
+					hdr = NLMSG_NEXT(hdr, len);
+					continue;
+				case NLMSG_DONE:
+					break;
+			}
+			break;
+		}
+	}
+
+	if (out_aevent)
+	{
+		rta = XFRM_RTA(out, struct xfrm_aevent_id);
+		rtasize = XFRM_PAYLOAD(out, struct xfrm_aevent_id);
+		while (RTA_OK(rta, rtasize))
+		{
+			if (rta->rta_type == XFRMA_LTIME_VAL &&
+				RTA_PAYLOAD(rta) == sizeof(**lifetime))
+			{
+				free(*lifetime);
+				*lifetime = malloc(RTA_PAYLOAD(rta));
+				memcpy(*lifetime, RTA_DATA(rta), RTA_PAYLOAD(rta));
+			}
+			if (rta->rta_type == XFRMA_REPLAY_VAL &&
+				RTA_PAYLOAD(rta) == sizeof(**replay))
+			{
+				free(*replay);
+				*replay = malloc(RTA_PAYLOAD(rta));
+				memcpy(*replay, RTA_DATA(rta), RTA_PAYLOAD(rta));
+			}
+			if (rta->rta_type == XFRMA_REPLAY_ESN_VAL &&
+				RTA_PAYLOAD(rta) >= sizeof(**replay_esn))
+			{
+				free(*replay_esn);
+				*replay_esn = malloc(RTA_PAYLOAD(rta));
+				*replay_esn_len = RTA_PAYLOAD(rta);
+				memcpy(*replay_esn, RTA_DATA(rta), RTA_PAYLOAD(rta));
+			}
+			rta = RTA_NEXT(rta, rtasize);
+		}
+	}
+	free(out);
+}
+
+METHOD(kernel_ipsec_t, query_sa, status_t,
+	private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
+	u_int32_t spi, u_int8_t protocol, mark_t mark,
+	u_int64_t *bytes, u_int64_t *packets, time_t *time)
+{
+	netlink_buf_t request;
+	struct nlmsghdr *out = NULL, *hdr;
+	struct xfrm_usersa_id *sa_id;
+	struct xfrm_usersa_info *sa = NULL;
+	status_t status = FAILED;
+	size_t len;
+
+	memset(&request, 0, sizeof(request));
+
+	DBG2(DBG_KNL, "querying SAD entry with SPI %.8x  (mark %u/0x%08x)",
+				   ntohl(spi), mark.value, mark.mask);
+
+	hdr = &request.hdr;
+	hdr->nlmsg_flags = NLM_F_REQUEST;
+	hdr->nlmsg_type = XFRM_MSG_GETSA;
+	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
+
+	sa_id = NLMSG_DATA(hdr);
+	host2xfrm(dst, &sa_id->daddr);
+	sa_id->spi = spi;
+	sa_id->proto = protocol;
+	sa_id->family = dst->get_family(dst);
+
+	if (!add_mark(hdr, sizeof(request), mark))
+	{
+		return FAILED;
+	}
+
+	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);
+
+					if (mark.value)
+					{
+						DBG1(DBG_KNL, "querying SAD entry with SPI %.8x  "
+									  "(mark %u/0x%08x) failed: %s (%d)",
+									   ntohl(spi), mark.value, mark.mask,
+									   strerror(-err->error), -err->error);
+					}
+					else
+					{
+						DBG1(DBG_KNL, "querying SAD entry with SPI %.8x "
+									  "failed: %s (%d)", ntohl(spi),
+									   strerror(-err->error), -err->error);
+					}
+					break;
+				}
+				default:
+					hdr = NLMSG_NEXT(hdr, len);
+					continue;
+				case NLMSG_DONE:
+					break;
+			}
+			break;
+		}
+	}
+
+	if (sa == NULL)
+	{
+		DBG2(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi));
+	}
+	else
+	{
+		if (bytes)
+		{
+			*bytes = sa->curlft.bytes;
+		}
+		if (packets)
+		{
+			*packets = sa->curlft.packets;
+		}
+		if (time)
+		{	/* curlft contains an "use" time, but that contains a timestamp
+			 * of the first use, not the last. Last use time must be queried
+			 * on the policy on Linux */
+			*time = 0;
+		}
+		status = SUCCESS;
+	}
+	memwipe(out, len);
+	free(out);
+	return status;
+}
+
+METHOD(kernel_ipsec_t, del_sa, status_t,
+	private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
+	u_int32_t spi, u_int8_t protocol, u_int16_t cpi, mark_t mark)
+{
+	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, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0, mark);
+	}
+
+	memset(&request, 0, sizeof(request));
+
+	DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x  (mark %u/0x%08x)",
+				   ntohl(spi), mark.value, mark.mask);
+
+	hdr = &request.hdr;
+	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 = NLMSG_DATA(hdr);
+	host2xfrm(dst, &sa_id->daddr);
+	sa_id->spi = spi;
+	sa_id->proto = protocol;
+	sa_id->family = dst->get_family(dst);
+
+	if (!add_mark(hdr, sizeof(request), mark))
+	{
+		return FAILED;
+	}
+
+	switch (this->socket_xfrm->send_ack(this->socket_xfrm, hdr))
+	{
+		case SUCCESS:
+			DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x (mark %u/0x%08x)",
+				 ntohl(spi), mark.value, mark.mask);
+			return SUCCESS;
+		case NOT_FOUND:
+			return NOT_FOUND;
+		default:
+			if (mark.value)
+			{
+				DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x "
+					 "(mark %u/0x%08x)", ntohl(spi), mark.value, mark.mask);
+			}
+			else
+			{
+				DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x",
+					 ntohl(spi));
+			}
+			return FAILED;
+	}
+}
+
+METHOD(kernel_ipsec_t, update_sa, status_t,
+	private_kernel_netlink_ipsec_t *this, u_int32_t spi, u_int8_t protocol,
+	u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
+	bool old_encap, bool new_encap, mark_t mark)
+{
+	netlink_buf_t request;
+	struct nlmsghdr *hdr, *out = NULL;
+	struct xfrm_usersa_id *sa_id;
+	struct xfrm_usersa_info *out_sa = NULL, *sa;
+	size_t len;
+	struct rtattr *rta;
+	size_t rtasize;
+	struct xfrm_encap_tmpl* tmpl = NULL;
+	struct xfrm_replay_state *replay = NULL;
+	struct xfrm_replay_state_esn *replay_esn = NULL;
+	struct xfrm_lifetime_cur *lifetime = NULL;
+	u_int32_t replay_esn_len = 0;
+	status_t status = FAILED;
+
+	/* 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, mark);
+	}
+
+	memset(&request, 0, sizeof(request));
+
+	DBG2(DBG_KNL, "querying SAD entry with SPI %.8x for update", ntohl(spi));
+
+	/* query the existing SA first */
+	hdr = &request.hdr;
+	hdr->nlmsg_flags = NLM_F_REQUEST;
+	hdr->nlmsg_type = XFRM_MSG_GETSA;
+	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
+
+	sa_id = NLMSG_DATA(hdr);
+	host2xfrm(dst, &sa_id->daddr);
+	sa_id->spi = spi;
+	sa_id->proto = protocol;
+	sa_id->family = dst->get_family(dst);
+
+	if (!add_mark(hdr, sizeof(request), mark))
+	{
+		return FAILED;
+	}
+
+	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:
+				{
+					out_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 (out_sa == NULL)
+	{
+		DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi));
+		goto failed;
+	}
+
+	get_replay_state(this, spi, protocol, dst, mark, &replay_esn,
+					 &replay_esn_len, &replay, &lifetime);
+
+	/* delete the old SA (without affecting the IPComp SA) */
+	if (del_sa(this, src, dst, spi, protocol, 0, mark) != SUCCESS)
+	{
+		DBG1(DBG_KNL, "unable to delete old SAD entry with SPI %.8x",
+					   ntohl(spi));
+		goto failed;
+	}
+
+	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 = &request.hdr;
+	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+	hdr->nlmsg_type = XFRM_MSG_NEWSA;
+	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
+	sa = NLMSG_DATA(hdr);
+	memcpy(sa, NLMSG_DATA(out), sizeof(struct xfrm_usersa_info));
+	sa->family = new_dst->get_family(new_dst);
+
+	if (!src->ip_equals(src, new_src))
+	{
+		host2xfrm(new_src, &sa->saddr);
+	}
+	if (!dst->ip_equals(dst, new_dst))
+	{
+		host2xfrm(new_dst, &sa->id.daddr);
+	}
+
+	rta = XFRM_RTA(out, struct xfrm_usersa_info);
+	rtasize = XFRM_PAYLOAD(out, struct xfrm_usersa_info);
+	while (RTA_OK(rta, rtasize))
+	{
+		/* copy all attributes, but not XFRMA_ENCAP if we are disabling it */
+		if (rta->rta_type != XFRMA_ENCAP || new_encap)
+		{
+			if (rta->rta_type == XFRMA_ENCAP)
+			{	/* update encap tmpl */
+				tmpl = RTA_DATA(rta);
+				tmpl->encap_sport = ntohs(new_src->get_port(new_src));
+				tmpl->encap_dport = ntohs(new_dst->get_port(new_dst));
+			}
+			netlink_add_attribute(hdr, rta->rta_type,
+								  chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)),
+								  sizeof(request));
+		}
+		rta = RTA_NEXT(rta, rtasize);
+	}
+
+	if (tmpl == NULL && new_encap)
+	{	/* add tmpl if we are enabling it */
+		tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP, sizeof(*tmpl));
+		if (!tmpl)
+		{
+			goto failed;
+		}
+		tmpl->encap_type = UDP_ENCAP_ESPINUDP;
+		tmpl->encap_sport = ntohs(new_src->get_port(new_src));
+		tmpl->encap_dport = ntohs(new_dst->get_port(new_dst));
+		memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t));
+	}
+
+	if (replay_esn)
+	{
+		struct xfrm_replay_state_esn *state;
+
+		state = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_ESN_VAL,
+								replay_esn_len);
+		if (!state)
+		{
+			goto failed;
+		}
+		memcpy(state, replay_esn, replay_esn_len);
+	}
+	else if (replay)
+	{
+		struct xfrm_replay_state *state;
+
+		state = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_VAL,
+								sizeof(*state));
+		if (!state)
+		{
+			goto failed;
+		}
+		memcpy(state, replay, sizeof(*state));
+	}
+	else
+	{
+		DBG1(DBG_KNL, "unable to copy replay state from old SAD entry with "
+			 "SPI %.8x", ntohl(spi));
+	}
+	if (lifetime)
+	{
+		struct xfrm_lifetime_cur *state;
+
+		state = netlink_reserve(hdr, sizeof(request), XFRMA_LTIME_VAL,
+								sizeof(*state));
+		if (!state)
+		{
+			goto failed;
+		}
+		memcpy(state, lifetime, sizeof(*state));
+	}
+	else
+	{
+		DBG1(DBG_KNL, "unable to copy usage stats from old SAD entry with "
+			 "SPI %.8x", ntohl(spi));
+	}
+
+	if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
+	{
+		DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi));
+		goto failed;
+	}
+
+	status = SUCCESS;
+failed:
+	free(replay);
+	free(replay_esn);
+	free(lifetime);
+	memwipe(out, len);
+	memwipe(&request, sizeof(request));
+	free(out);
+
+	return status;
+}
+
+METHOD(kernel_ipsec_t, flush_sas, status_t,
+	private_kernel_netlink_ipsec_t *this)
+{
+	netlink_buf_t request;
+	struct nlmsghdr *hdr;
+	struct xfrm_usersa_flush *flush;
+	struct {
+		u_int8_t proto;
+		char *name;
+	} protos[] = {
+		{ IPPROTO_AH, "AH" },
+		{ IPPROTO_ESP, "ESP" },
+		{ IPPROTO_COMP, "IPComp" },
+	};
+	int i;
+
+	memset(&request, 0, sizeof(request));
+
+	hdr = &request.hdr;
+	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+	hdr->nlmsg_type = XFRM_MSG_FLUSHSA;
+	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_flush));
+
+	flush = NLMSG_DATA(hdr);
+
+	for (i = 0; i < countof(protos); i++)
+	{
+		DBG2(DBG_KNL, "flushing all %s SAD entries", protos[i].name);
+
+		flush->proto = protos[i].proto;
+
+		if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
+		{
+			DBG1(DBG_KNL, "unable to flush %s SAD entries", protos[i].name);
+			return FAILED;
+		}
+	}
+	return SUCCESS;
+}
+
+/**
+ * Add or update a policy in the kernel.
+ *
+ * Note: The mutex has to be locked when entering this function
+ * and is unlocked here in any case.
+ */
+static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
+	policy_entry_t *policy, policy_sa_t *mapping, bool update)
+{
+	netlink_buf_t request;
+	policy_entry_t clone;
+	ipsec_sa_t *ipsec = mapping->sa;
+	struct xfrm_userpolicy_info *policy_info;
+	struct nlmsghdr *hdr;
+	status_t status;
+	int i;
+
+	/* clone the policy so we are able to check it out again later */
+	memcpy(&clone, policy, sizeof(policy_entry_t));
+
+	memset(&request, 0, sizeof(request));
+	hdr = &request.hdr;
+	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+	hdr->nlmsg_type = update ? XFRM_MSG_UPDPOLICY : XFRM_MSG_NEWPOLICY;
+	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info));
+
+	policy_info = NLMSG_DATA(hdr);
+	policy_info->sel = policy->sel;
+	policy_info->dir = policy->direction;
+
+	/* calculate priority based on selector size, small size = high prio */
+	policy_info->priority = mapping->priority;
+	policy_info->action = mapping->type != POLICY_DROP ? XFRM_POLICY_ALLOW
+													   : XFRM_POLICY_BLOCK;
+	policy_info->share = XFRM_SHARE_ANY;
+
+	/* policies don't expire */
+	policy_info->lft.soft_byte_limit = XFRM_INF;
+	policy_info->lft.soft_packet_limit = XFRM_INF;
+	policy_info->lft.hard_byte_limit = XFRM_INF;
+	policy_info->lft.hard_packet_limit = XFRM_INF;
+	policy_info->lft.soft_add_expires_seconds = 0;
+	policy_info->lft.hard_add_expires_seconds = 0;
+	policy_info->lft.soft_use_expires_seconds = 0;
+	policy_info->lft.hard_use_expires_seconds = 0;
+
+	if (mapping->type == POLICY_IPSEC)
+	{
+		struct xfrm_user_tmpl *tmpl;
+		struct {
+			u_int8_t proto;
+			bool use;
+		} protos[] = {
+			{ IPPROTO_COMP, ipsec->cfg.ipcomp.transform != IPCOMP_NONE },
+			{ IPPROTO_ESP, ipsec->cfg.esp.use },
+			{ IPPROTO_AH, ipsec->cfg.ah.use },
+		};
+		ipsec_mode_t proto_mode = ipsec->cfg.mode;
+		int count = 0;
+
+		for (i = 0; i < countof(protos); i++)
+		{
+			if (protos[i].use)
+			{
+				count++;
+			}
+		}
+		tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_TMPL,
+							   count * sizeof(*tmpl));
+		if (!tmpl)
+		{
+			this->mutex->unlock(this->mutex);
+			return FAILED;
+		}
+
+		for (i = 0; i < countof(protos); i++)
+		{
+			if (!protos[i].use)
+			{
+				continue;
+			}
+			tmpl->reqid = ipsec->cfg.reqid;
+			tmpl->id.proto = protos[i].proto;
+			tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
+			tmpl->mode = mode2kernel(proto_mode);
+			tmpl->optional = protos[i].proto == IPPROTO_COMP &&
+							 policy->direction != POLICY_OUT;
+			tmpl->family = ipsec->src->get_family(ipsec->src);
+
+			if (proto_mode == MODE_TUNNEL || proto_mode == MODE_BEET)
+			{	/* only for tunnel mode */
+				host2xfrm(ipsec->src, &tmpl->saddr);
+				host2xfrm(ipsec->dst, &tmpl->id.daddr);
+			}
+
+			tmpl++;
+
+			/* use transport mode for other SAs */
+			proto_mode = MODE_TRANSPORT;
+		}
+	}
+
+	if (!add_mark(hdr, sizeof(request), ipsec->mark))
+	{
+		this->mutex->unlock(this->mutex);
+		return FAILED;
+	}
+	this->mutex->unlock(this->mutex);
+
+	status = this->socket_xfrm->send_ack(this->socket_xfrm, hdr);
+	if (status == ALREADY_DONE && !update)
+	{
+		DBG1(DBG_KNL, "policy already exists, try to update it");
+		hdr->nlmsg_type = XFRM_MSG_UPDPOLICY;
+		status = this->socket_xfrm->send_ack(this->socket_xfrm, hdr);
+	}
+	if (status != SUCCESS)
+	{
+		return FAILED;
+	}
+
+	/* find the policy again */
+	this->mutex->lock(this->mutex);
+	policy = this->policies->get(this->policies, &clone);
+	if (!policy ||
+		 policy->used_by->find_first(policy->used_by,
+									 NULL, (void**)&mapping) != SUCCESS)
+	{	/* policy or mapping is already gone, ignore */
+		this->mutex->unlock(this->mutex);
+		return SUCCESS;
+	}
+
+	/* install a route, if:
+	 * - this is a forward policy (to just get one for each child)
+	 * - we are in tunnel/BEET mode or install a bypass policy
+	 * - routing is not disabled via strongswan.conf
+	 */
+	if (policy->direction == POLICY_FWD && this->install_routes &&
+		(mapping->type != POLICY_IPSEC || ipsec->cfg.mode != MODE_TRANSPORT))
+	{
+		policy_sa_fwd_t *fwd = (policy_sa_fwd_t*)mapping;
+		route_entry_t *route;
+		host_t *iface;
+
+		INIT(route,
+			.prefixlen = policy->sel.prefixlen_s,
+		);
+
+		if (charon->kernel->get_address_by_ts(charon->kernel, fwd->dst_ts,
+											  &route->src_ip, NULL) == SUCCESS)
+		{
+			/* get the nexthop to src (src as we are in POLICY_FWD) */
+			if (!ipsec->src->is_anyaddr(ipsec->src))
+			{
+				route->gateway = charon->kernel->get_nexthop(charon->kernel,
+													ipsec->src, -1, ipsec->dst);
+			}
+			else
+			{	/* for shunt policies */
+				iface = xfrm2host(policy->sel.family, &policy->sel.saddr, 0);
+				route->gateway = charon->kernel->get_nexthop(charon->kernel,
+												iface, policy->sel.prefixlen_s,
+												route->src_ip);
+				iface->destroy(iface);
+			}
+			route->dst_net = chunk_alloc(policy->sel.family == AF_INET ? 4 : 16);
+			memcpy(route->dst_net.ptr, &policy->sel.saddr, route->dst_net.len);
+
+			/* get the interface to install the route for. If we have a local
+			 * address, use it. Otherwise (for shunt policies) use the
+			 * routes source address. */
+			iface = ipsec->dst;
+			if (iface->is_anyaddr(iface))
+			{
+				iface = route->src_ip;
+			}
+			/* install route via outgoing interface */
+			if (!charon->kernel->get_interface(charon->kernel, iface,
+											   &route->if_name))
+			{
+				this->mutex->unlock(this->mutex);
+				route_entry_destroy(route);
+				return SUCCESS;
+			}
+
+			if (policy->route)
+			{
+				route_entry_t *old = policy->route;
+				if (route_entry_equals(old, route))
+				{
+					this->mutex->unlock(this->mutex);
+					route_entry_destroy(route);
+					return SUCCESS;
+				}
+				/* uninstall previously installed route */
+				if (charon->kernel->del_route(charon->kernel, old->dst_net,
+										old->prefixlen, old->gateway,
+										old->src_ip, old->if_name) != SUCCESS)
+				{
+					DBG1(DBG_KNL, "error uninstalling route installed with "
+								  "policy %R === %R %N", fwd->src_ts,
+								   fwd->dst_ts, policy_dir_names,
+								   policy->direction);
+				}
+				route_entry_destroy(old);
+				policy->route = NULL;
+			}
+
+			DBG2(DBG_KNL, "installing route: %R via %H src %H dev %s",
+				 fwd->src_ts, route->gateway, route->src_ip, route->if_name);
+			switch (charon->kernel->add_route(charon->kernel, 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;
+}
+
+METHOD(kernel_ipsec_t, add_policy, status_t,
+	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, policy_type_t type, ipsec_sa_cfg_t *sa,
+	mark_t mark, policy_priority_t priority)
+{
+	policy_entry_t *policy, *current;
+	policy_sa_t *assigned_sa, *current_sa;
+	enumerator_t *enumerator;
+	bool found = FALSE, update = TRUE;
+
+	/* create a policy */
+	INIT(policy,
+		.sel = ts2selector(src_ts, dst_ts),
+		.mark = mark.value & mark.mask,
+		.direction = direction,
+		.reqid = sa->reqid,
+	);
+
+	/* find the policy, which matches EXACTLY */
+	this->mutex->lock(this->mutex);
+	current = this->policies->get(this->policies, policy);
+	if (current)
+	{
+		if (current->reqid && sa->reqid && current->reqid != sa->reqid)
+		{
+			DBG1(DBG_CFG, "unable to install policy %R === %R %N (mark "
+				 "%u/0x%08x) for reqid %u, the same policy for reqid %u exists",
+				 src_ts, dst_ts, policy_dir_names, direction,
+				 mark.value, mark.mask, sa->reqid, current->reqid);
+			policy_entry_destroy(this, policy);
+			this->mutex->unlock(this->mutex);
+			return INVALID_STATE;
+		}
+		/* use existing policy */
+		DBG2(DBG_KNL, "policy %R === %R %N  (mark %u/0x%08x) "
+					  "already exists, increasing refcount",
+					   src_ts, dst_ts, policy_dir_names, direction,
+					   mark.value, mark.mask);
+		policy_entry_destroy(this, policy);
+		policy = current;
+		found = TRUE;
+	}
+	else
+	{	/* use the new one, if we have no such policy */
+		policy->used_by = linked_list_create();
+		this->policies->put(this->policies, policy, policy);
+	}
+
+	/* cache the assigned IPsec SA */
+	assigned_sa = policy_sa_create(this, direction, type, src, dst, src_ts,
+								   dst_ts, mark, sa);
+	assigned_sa->priority = get_priority(policy, priority);
+
+	/* insert the SA according to its priority */
+	enumerator = policy->used_by->create_enumerator(policy->used_by);
+	while (enumerator->enumerate(enumerator, (void**)&current_sa))
+	{
+		if (current_sa->priority >= assigned_sa->priority)
+		{
+			break;
+		}
+		update = FALSE;
+	}
+	policy->used_by->insert_before(policy->used_by, enumerator,
+								   assigned_sa);
+	enumerator->destroy(enumerator);
+
+	if (!update)
+	{	/* we don't update the policy if the priority is lower than that of
+		 * the currently installed one */
+		this->mutex->unlock(this->mutex);
+		return SUCCESS;
+	}
+
+	if (this->policy_update)
+	{
+		found = TRUE;
+	}
+
+	DBG2(DBG_KNL, "%s policy %R === %R %N  (mark %u/0x%08x)",
+				   found ? "updating" : "adding", src_ts, dst_ts,
+				   policy_dir_names, direction, mark.value, mark.mask);
+
+	if (add_policy_internal(this, policy, assigned_sa, found) != SUCCESS)
+	{
+		DBG1(DBG_KNL, "unable to %s policy %R === %R %N",
+					   found ? "update" : "add", src_ts, dst_ts,
+					   policy_dir_names, direction);
+		return FAILED;
+	}
+	return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, query_policy, status_t,
+	private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts,
+	traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+	time_t *use_time)
+{
+	netlink_buf_t request;
+	struct nlmsghdr *out = NULL, *hdr;
+	struct xfrm_userpolicy_id *policy_id;
+	struct xfrm_userpolicy_info *policy = NULL;
+	size_t len;
+
+	memset(&request, 0, sizeof(request));
+
+	DBG2(DBG_KNL, "querying policy %R === %R %N  (mark %u/0x%08x)",
+				   src_ts, dst_ts, policy_dir_names, direction,
+				   mark.value, mark.mask);
+
+	hdr = &request.hdr;
+	hdr->nlmsg_flags = NLM_F_REQUEST;
+	hdr->nlmsg_type = XFRM_MSG_GETPOLICY;
+	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id));
+
+	policy_id = NLMSG_DATA(hdr);
+	policy_id->sel = ts2selector(src_ts, dst_ts);
+	policy_id->dir = direction;
+
+	if (!add_mark(hdr, sizeof(request), mark))
+	{
+		return FAILED;
+	}
+
+	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_NEWPOLICY:
+				{
+					policy = NLMSG_DATA(hdr);
+					break;
+				}
+				case NLMSG_ERROR:
+				{
+					struct nlmsgerr *err = NLMSG_DATA(hdr);
+					DBG1(DBG_KNL, "querying policy failed: %s (%d)",
+								   strerror(-err->error), -err->error);
+					break;
+				}
+				default:
+					hdr = NLMSG_NEXT(hdr, len);
+					continue;
+				case NLMSG_DONE:
+					break;
+			}
+			break;
+		}
+	}
+
+	if (policy == NULL)
+	{
+		DBG2(DBG_KNL, "unable to query policy %R === %R %N", src_ts, dst_ts,
+					   policy_dir_names, direction);
+		free(out);
+		return FAILED;
+	}
+
+	if (policy->curlft.use_time)
+	{
+		/* we need the monotonic time, but the kernel returns system time. */
+		*use_time = time_monotonic(NULL) - (time(NULL) - policy->curlft.use_time);
+	}
+	else
+	{
+		*use_time = 0;
+	}
+
+	free(out);
+	return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, del_policy, status_t,
+	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, policy_type_t type, ipsec_sa_cfg_t *sa,
+	mark_t mark, policy_priority_t prio)
+{
+	policy_entry_t *current, policy;
+	enumerator_t *enumerator;
+	policy_sa_t *mapping;
+	netlink_buf_t request;
+	struct nlmsghdr *hdr;
+	struct xfrm_userpolicy_id *policy_id;
+	bool is_installed = TRUE;
+	u_int32_t priority;
+	ipsec_sa_t assigned_sa = {
+		.src = src,
+		.dst = dst,
+		.mark = mark,
+		.cfg = *sa,
+	};
+
+	DBG2(DBG_KNL, "deleting policy %R === %R %N  (mark %u/0x%08x)",
+				   src_ts, dst_ts, policy_dir_names, direction,
+				   mark.value, mark.mask);
+
+	/* create a policy */
+	memset(&policy, 0, sizeof(policy_entry_t));
+	policy.sel = ts2selector(src_ts, dst_ts);
+	policy.mark = mark.value & mark.mask;
+	policy.direction = direction;
+
+	/* find the policy */
+	this->mutex->lock(this->mutex);
+	current = this->policies->get(this->policies, &policy);
+	if (!current)
+	{
+		if (mark.value)
+		{
+			DBG1(DBG_KNL, "deleting policy %R === %R %N  (mark %u/0x%08x) "
+						  "failed, not found", src_ts, dst_ts, policy_dir_names,
+						   direction, mark.value, mark.mask);
+		}
+		else
+		{
+			DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found",
+						   src_ts, dst_ts, policy_dir_names, direction);
+		}
+		this->mutex->unlock(this->mutex);
+		return NOT_FOUND;
+	}
+
+	/* remove mapping to SA by reqid and priority */
+	priority = get_priority(current, prio);
+	enumerator = current->used_by->create_enumerator(current->used_by);
+	while (enumerator->enumerate(enumerator, (void**)&mapping))
+	{
+		if (priority == mapping->priority && type == mapping->type &&
+			ipsec_sa_equals(mapping->sa, &assigned_sa))
+		{
+			current->used_by->remove_at(current->used_by, enumerator);
+			policy_sa_destroy(mapping, &direction, this);
+			break;
+		}
+		is_installed = FALSE;
+	}
+	enumerator->destroy(enumerator);
+
+	if (current->used_by->get_count(current->used_by) > 0)
+	{	/* policy is used by more SAs, keep in kernel */
+		DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
+		if (!is_installed)
+		{	/* no need to update as the policy was not installed for this SA */
+			this->mutex->unlock(this->mutex);
+			return SUCCESS;
+		}
+
+		DBG2(DBG_KNL, "updating policy %R === %R %N  (mark %u/0x%08x)",
+					   src_ts, dst_ts, policy_dir_names, direction,
+					   mark.value, mark.mask);
+
+		current->used_by->get_first(current->used_by, (void**)&mapping);
+		if (add_policy_internal(this, current, mapping, TRUE) != SUCCESS)
+		{
+			DBG1(DBG_KNL, "unable to update policy %R === %R %N",
+						   src_ts, dst_ts, policy_dir_names, direction);
+			return FAILED;
+		}
+		return SUCCESS;
+	}
+
+	memset(&request, 0, sizeof(request));
+
+	hdr = &request.hdr;
+	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+	hdr->nlmsg_type = XFRM_MSG_DELPOLICY;
+	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id));
+
+	policy_id = NLMSG_DATA(hdr);
+	policy_id->sel = current->sel;
+	policy_id->dir = direction;
+
+	if (!add_mark(hdr, sizeof(request), mark))
+	{
+		this->mutex->unlock(this->mutex);
+		return FAILED;
+	}
+
+	if (current->route)
+	{
+		route_entry_t *route = current->route;
+		if (charon->kernel->del_route(charon->kernel, 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);
+		}
+	}
+
+	this->policies->remove(this->policies, current);
+	policy_entry_destroy(this, current);
+	this->mutex->unlock(this->mutex);
+
+	if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
+	{
+		if (mark.value)
+		{
+			DBG1(DBG_KNL, "unable to delete policy %R === %R %N  "
+						  "(mark %u/0x%08x)", src_ts, dst_ts, policy_dir_names,
+						   direction, mark.value, mark.mask);
+		}
+		else
+		{
+			DBG1(DBG_KNL, "unable to delete policy %R === %R %N",
+						   src_ts, dst_ts, policy_dir_names, direction);
+		}
+		return FAILED;
+	}
+	return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, flush_policies, status_t,
+	private_kernel_netlink_ipsec_t *this)
+{
+	netlink_buf_t request;
+	struct nlmsghdr *hdr;
+
+	memset(&request, 0, sizeof(request));
+
+	DBG2(DBG_KNL, "flushing all policies from SPD");
+
+	hdr = &request.hdr;
+	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+	hdr->nlmsg_type = XFRM_MSG_FLUSHPOLICY;
+	hdr->nlmsg_len = NLMSG_LENGTH(0); /* no data associated */
+
+	/* by adding an rtattr of type  XFRMA_POLICY_TYPE we could restrict this
+	 * to main or sub policies (default is main) */
+
+	if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
+	{
+		DBG1(DBG_KNL, "unable to flush SPD entries");
+		return FAILED;
+	}
+	return SUCCESS;
+}
+
+/**
+ * Bypass socket using a per-socket policy
+ */
+static bool add_socket_bypass(private_kernel_netlink_ipsec_t *this,
+							  int fd, int family)
+{
+	struct xfrm_userpolicy_info policy;
+	u_int sol, ipsec_policy;
+
+	switch (family)
+	{
+		case AF_INET:
+			sol = SOL_IP;
+			ipsec_policy = IP_XFRM_POLICY;
+			break;
+		case AF_INET6:
+			sol = SOL_IPV6;
+			ipsec_policy = IPV6_XFRM_POLICY;
+			break;
+		default:
+			return FALSE;
+	}
+
+	memset(&policy, 0, sizeof(policy));
+	policy.action = XFRM_POLICY_ALLOW;
+	policy.sel.family = family;
+
+	policy.dir = XFRM_POLICY_OUT;
+	if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
+	{
+		DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
+					   strerror(errno));
+		return FALSE;
+	}
+	policy.dir = XFRM_POLICY_IN;
+	if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
+	{
+		DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
+					   strerror(errno));
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/**
+ * Port based IKE bypass policy
+ */
+typedef struct {
+	/** address family */
+	int family;
+	/** layer 4 protocol */
+	int proto;
+	/** port number, network order */
+	u_int16_t port;
+} bypass_t;
+
+/**
+ * Add or remove a bypass policy from/to kernel
+ */
+static bool manage_bypass(private_kernel_netlink_ipsec_t *this,
+						  int type, policy_dir_t dir, bypass_t *bypass)
+{
+	netlink_buf_t request;
+	struct xfrm_selector *sel;
+	struct nlmsghdr *hdr;
+
+	memset(&request, 0, sizeof(request));
+	hdr = &request.hdr;
+	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+	hdr->nlmsg_type = type;
+
+	if (type == XFRM_MSG_NEWPOLICY)
+	{
+		struct xfrm_userpolicy_info *policy;
+
+		hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info));
+
+		policy = NLMSG_DATA(hdr);
+		policy->dir = dir;
+		policy->priority = 32;
+		policy->action = XFRM_POLICY_ALLOW;
+		policy->share = XFRM_SHARE_ANY;
+
+		policy->lft.soft_byte_limit = XFRM_INF;
+		policy->lft.soft_packet_limit = XFRM_INF;
+		policy->lft.hard_byte_limit = XFRM_INF;
+		policy->lft.hard_packet_limit = XFRM_INF;
+
+		sel = &policy->sel;
+	}
+	else /* XFRM_MSG_DELPOLICY */
+	{
+		struct xfrm_userpolicy_id *policy;
+
+		hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id));
+
+		policy = NLMSG_DATA(hdr);
+		policy->dir = dir;
+
+		sel = &policy->sel;
+	}
+
+	sel->family = bypass->family;
+	sel->proto = bypass->proto;
+	if (dir == POLICY_IN)
+	{
+		sel->dport = bypass->port;
+		sel->dport_mask = 0xffff;
+	}
+	else
+	{
+		sel->sport = bypass->port;
+		sel->sport_mask = 0xffff;
+	}
+	return this->socket_xfrm->send_ack(this->socket_xfrm, hdr) == SUCCESS;
+}
+
+/**
+ * Bypass socket using a port-based bypass policy
+ */
+static bool add_port_bypass(private_kernel_netlink_ipsec_t *this,
+							int fd, int family)
+{
+	union {
+		struct sockaddr sa;
+		struct sockaddr_in in;
+		struct sockaddr_in6 in6;
+	} saddr;
+	socklen_t len;
+	bypass_t bypass = {
+		.family = family,
+	};
+
+	len = sizeof(saddr);
+	if (getsockname(fd, &saddr.sa, &len) != 0)
+	{
+		return FALSE;
+	}
+#ifdef SO_PROTOCOL /* since 2.6.32 */
+	len = sizeof(bypass.proto);
+	if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &bypass.proto, &len) != 0)
+#endif
+	{	/* assume UDP if SO_PROTOCOL not supported */
+		bypass.proto = IPPROTO_UDP;
+	}
+	switch (family)
+	{
+		case AF_INET:
+			bypass.port = saddr.in.sin_port;
+			break;
+		case AF_INET6:
+			bypass.port = saddr.in6.sin6_port;
+			break;
+		default:
+			return FALSE;
+	}
+
+	if (!manage_bypass(this, XFRM_MSG_NEWPOLICY, POLICY_IN, &bypass))
+	{
+		return FALSE;
+	}
+	if (!manage_bypass(this, XFRM_MSG_NEWPOLICY, POLICY_OUT, &bypass))
+	{
+		manage_bypass(this, XFRM_MSG_DELPOLICY, POLICY_IN, &bypass);
+		return FALSE;
+	}
+	array_insert(this->bypass, ARRAY_TAIL, &bypass);
+
+	return TRUE;
+}
+
+/**
+ * Remove installed port based bypass policy
+ */
+static void remove_port_bypass(bypass_t *bypass, int idx,
+							   private_kernel_netlink_ipsec_t *this)
+{
+	manage_bypass(this, XFRM_MSG_DELPOLICY, POLICY_OUT, bypass);
+	manage_bypass(this, XFRM_MSG_DELPOLICY, POLICY_IN, bypass);
+}
+
+METHOD(kernel_ipsec_t, bypass_socket, bool,
+	private_kernel_netlink_ipsec_t *this, int fd, int family)
+{
+	if (lib->settings->get_bool(lib->settings,
+					"%s.plugins.kernel-netlink.port_bypass", FALSE, lib->ns))
+	{
+		return add_port_bypass(this, fd, family);
+	}
+	return add_socket_bypass(this, fd, family);
+}
+
+METHOD(kernel_ipsec_t, enable_udp_decap, bool,
+	private_kernel_netlink_ipsec_t *this, int fd, int family, u_int16_t port)
+{
+	int type = UDP_ENCAP_ESPINUDP;
+
+	if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
+	{
+		DBG1(DBG_KNL, "unable to set UDP_ENCAP: %s", strerror(errno));
+		return FALSE;
+	}
+	return TRUE;
+}
+
+METHOD(kernel_ipsec_t, destroy, void,
+	private_kernel_netlink_ipsec_t *this)
+{
+	enumerator_t *enumerator;
+	policy_entry_t *policy;
+
+	array_destroy_function(this->bypass,
+						   (array_callback_t)remove_port_bypass, this);
+	if (this->socket_xfrm_events > 0)
+	{
+		lib->watcher->remove(lib->watcher, this->socket_xfrm_events);
+		close(this->socket_xfrm_events);
+	}
+	DESTROY_IF(this->socket_xfrm);
+	enumerator = this->policies->create_enumerator(this->policies);
+	while (enumerator->enumerate(enumerator, &policy, &policy))
+	{
+		policy_entry_destroy(this, policy);
+	}
+	enumerator->destroy(enumerator);
+	this->policies->destroy(this->policies);
+	this->sas->destroy(this->sas);
+	this->mutex->destroy(this->mutex);
+	free(this);
+}
+
+/*
+ * Described in header.
+ */
+kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
+{
+	private_kernel_netlink_ipsec_t *this;
+	bool register_for_events = TRUE;
+	FILE *f;
+
+	INIT(this,
+		.public = {
+			.interface = {
+				.get_features = _get_features,
+				.get_spi = _get_spi,
+				.get_cpi = _get_cpi,
+				.add_sa  = _add_sa,
+				.update_sa = _update_sa,
+				.query_sa = _query_sa,
+				.del_sa = _del_sa,
+				.flush_sas = _flush_sas,
+				.add_policy = _add_policy,
+				.query_policy = _query_policy,
+				.del_policy = _del_policy,
+				.flush_policies = _flush_policies,
+				.bypass_socket = _bypass_socket,
+				.enable_udp_decap = _enable_udp_decap,
+				.destroy = _destroy,
+			},
+		},
+		.policies = hashtable_create((hashtable_hash_t)policy_hash,
+									 (hashtable_equals_t)policy_equals, 32),
+		.sas = hashtable_create((hashtable_hash_t)ipsec_sa_hash,
+								(hashtable_equals_t)ipsec_sa_equals, 32),
+		.bypass = array_create(sizeof(bypass_t), 0),
+		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+		.policy_update = lib->settings->get_bool(lib->settings,
+					"%s.plugins.kernel-netlink.policy_update", FALSE, lib->ns),
+		.install_routes = lib->settings->get_bool(lib->settings,
+							"%s.install_routes", TRUE, lib->ns),
+		.proto_port_transport = lib->settings->get_bool(lib->settings,
+						"%s.plugins.kernel-netlink.set_proto_port_transport_sa",
+						FALSE, lib->ns),
+	);
+
+	if (streq(lib->ns, "starter"))
+	{	/* starter has no threads, so we do not register for kernel events */
+		register_for_events = FALSE;
+	}
+
+	f = fopen("/proc/sys/net/core/xfrm_acq_expires", "w");
+	if (f)
+	{
+		fprintf(f, "%u", lib->settings->get_int(lib->settings,
+								"%s.plugins.kernel-netlink.xfrm_acq_expires",
+								DEFAULT_ACQUIRE_LIFETIME, lib->ns));
+		fclose(f);
+	}
+
+	this->socket_xfrm = netlink_socket_create(NETLINK_XFRM, xfrm_msg_names,
+				lib->settings->get_bool(lib->settings,
+					"%s.plugins.kernel-netlink.parallel_xfrm", FALSE, lib->ns));
+	if (!this->socket_xfrm)
+	{
+		destroy(this);
+		return NULL;
+	}
+
+	if (register_for_events)
+	{
+		struct sockaddr_nl addr;
+
+		memset(&addr, 0, sizeof(addr));
+		addr.nl_family = AF_NETLINK;
+
+		/* 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)
+		{
+			DBG1(DBG_KNL, "unable to create XFRM event socket");
+			destroy(this);
+			return NULL;
+		}
+		addr.nl_groups = XFRMNLGRP(ACQUIRE) | XFRMNLGRP(EXPIRE) |
+						 XFRMNLGRP(MIGRATE) | XFRMNLGRP(MAPPING);
+		if (bind(this->socket_xfrm_events, (struct sockaddr*)&addr, sizeof(addr)))
+		{
+			DBG1(DBG_KNL, "unable to bind XFRM event socket");
+			destroy(this);
+			return NULL;
+		}
+		lib->watcher->add(lib->watcher, this->socket_xfrm_events, WATCHER_READ,
+						  (watcher_cb_t)receive_events, this);
+	}
+
+	return &this->public;
+}
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.h b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.h
similarity index 100%
rename from src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.h
rename to src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.h
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
new file mode 100644
index 0000000..f4394a1
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
@@ -0,0 +1,2686 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2005-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.
+ */
+
+/*
+ * Copyright (C) 2010 secunet Security Networks AG
+ * Copyright (C) 2010 Thomas Egerer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <sys/socket.h>
+#include <sys/utsname.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <unistd.h>
+#include <errno.h>
+#include <net/if.h>
+#ifdef HAVE_LINUX_FIB_RULES_H
+#include <linux/fib_rules.h>
+#endif
+
+#include "kernel_netlink_net.h"
+#include "kernel_netlink_shared.h"
+
+#include <daemon.h>
+#include <utils/debug.h>
+#include <threading/mutex.h>
+#include <threading/rwlock.h>
+#include <threading/rwlock_condvar.h>
+#include <threading/spinlock.h>
+#include <collections/hashtable.h>
+#include <collections/linked_list.h>
+#include <processing/jobs/callback_job.h>
+
+/** delay before firing roam events (ms) */
+#define ROAM_DELAY 100
+
+/** delay before reinstalling routes (ms) */
+#define ROUTE_DELAY 100
+
+/** maximum recursion when searching for addresses in get_route() */
+#define MAX_ROUTE_RECURSION 2
+
+#ifndef ROUTING_TABLE
+#define ROUTING_TABLE 0
+#endif
+
+#ifndef ROUTING_TABLE_PRIO
+#define ROUTING_TABLE_PRIO 0
+#endif
+
+ENUM(rt_msg_names, RTM_NEWLINK, RTM_GETRULE,
+	"RTM_NEWLINK",
+	"RTM_DELLINK",
+	"RTM_GETLINK",
+	"RTM_SETLINK",
+	"RTM_NEWADDR",
+	"RTM_DELADDR",
+	"RTM_GETADDR",
+	"31",
+	"RTM_NEWROUTE",
+	"RTM_DELROUTE",
+	"RTM_GETROUTE",
+	"35",
+	"RTM_NEWNEIGH",
+	"RTM_DELNEIGH",
+	"RTM_GETNEIGH",
+	"RTM_NEWRULE",
+	"RTM_DELRULE",
+	"RTM_GETRULE",
+);
+
+typedef struct addr_entry_t addr_entry_t;
+
+/**
+ * IP address in an iface_entry_t
+ */
+struct addr_entry_t {
+
+	/** the ip address */
+	host_t *ip;
+
+	/** address flags */
+	u_char flags;
+
+	/** scope of the address */
+	u_char scope;
+
+	/** number of times this IP is used, if virtual (i.e. managed by us) */
+	u_int refcount;
+
+	/** TRUE once it is installed, if virtual */
+	bool installed;
+};
+
+/**
+ * destroy a addr_entry_t object
+ */
+static void addr_entry_destroy(addr_entry_t *this)
+{
+	this->ip->destroy(this->ip);
+	free(this);
+}
+
+typedef struct iface_entry_t iface_entry_t;
+
+/**
+ * A network interface on this system, containing addr_entry_t's
+ */
+struct iface_entry_t {
+
+	/** interface index */
+	int ifindex;
+
+	/** name of the interface */
+	char ifname[IFNAMSIZ];
+
+	/** interface flags, as in netdevice(7) SIOCGIFFLAGS */
+	u_int flags;
+
+	/** list of addresses as host_t */
+	linked_list_t *addrs;
+
+	/** TRUE if usable by config */
+	bool usable;
+};
+
+/**
+ * destroy an interface entry
+ */
+static void iface_entry_destroy(iface_entry_t *this)
+{
+	this->addrs->destroy_function(this->addrs, (void*)addr_entry_destroy);
+	free(this);
+}
+
+/**
+ * find an interface entry by index
+ */
+static bool iface_entry_by_index(iface_entry_t *this, int *ifindex)
+{
+	return this->ifindex == *ifindex;
+}
+
+/**
+ * find an interface entry by name
+ */
+static bool iface_entry_by_name(iface_entry_t *this, char *ifname)
+{
+	return streq(this->ifname, ifname);
+}
+
+/**
+ * check if an interface is up
+ */
+static inline bool iface_entry_up(iface_entry_t *iface)
+{
+	return (iface->flags & IFF_UP) == IFF_UP;
+}
+
+/**
+ * check if an interface is up and usable
+ */
+static inline bool iface_entry_up_and_usable(iface_entry_t *iface)
+{
+	return iface->usable && iface_entry_up(iface);
+}
+
+typedef struct addr_map_entry_t addr_map_entry_t;
+
+/**
+ * Entry that maps an IP address to an interface entry
+ */
+struct addr_map_entry_t {
+	/** The IP address */
+	host_t *ip;
+
+	/** The address entry for this IP address */
+	addr_entry_t *addr;
+
+	/** The interface this address is installed on */
+	iface_entry_t *iface;
+};
+
+/**
+ * Hash a addr_map_entry_t object, all entries with the same IP address
+ * are stored in the same bucket
+ */
+static u_int addr_map_entry_hash(addr_map_entry_t *this)
+{
+	return chunk_hash(this->ip->get_address(this->ip));
+}
+
+/**
+ * Compare two addr_map_entry_t objects, two entries are equal if they are
+ * installed on the same interface
+ */
+static bool addr_map_entry_equals(addr_map_entry_t *a, addr_map_entry_t *b)
+{
+	return a->iface->ifindex == b->iface->ifindex &&
+		   a->ip->ip_equals(a->ip, b->ip);
+}
+
+/**
+ * Used with get_match this finds an address entry if it is installed on
+ * an up and usable interface
+ */
+static bool addr_map_entry_match_up_and_usable(addr_map_entry_t *a,
+											   addr_map_entry_t *b)
+{
+	return iface_entry_up_and_usable(b->iface) &&
+		   a->ip->ip_equals(a->ip, b->ip);
+}
+
+/**
+ * Used with get_match this finds an address entry if it is installed on
+ * any active local interface
+ */
+static bool addr_map_entry_match_up(addr_map_entry_t *a, addr_map_entry_t *b)
+{
+	return iface_entry_up(b->iface) && a->ip->ip_equals(a->ip, b->ip);
+}
+
+/**
+ * Used with get_match this finds an address entry if it is installed on
+ * any local interface
+ */
+static bool addr_map_entry_match(addr_map_entry_t *a, addr_map_entry_t *b)
+{
+	return a->ip->ip_equals(a->ip, b->ip);
+}
+
+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;
+};
+
+/**
+ * Clone a route_entry_t object.
+ */
+static route_entry_t *route_entry_clone(route_entry_t *this)
+{
+	route_entry_t *route;
+
+	INIT(route,
+		.if_name = strdup(this->if_name),
+		.src_ip = this->src_ip->clone(this->src_ip),
+		.gateway = this->gateway ? this->gateway->clone(this->gateway) : NULL,
+		.dst_net = chunk_clone(this->dst_net),
+		.prefixlen = this->prefixlen,
+	);
+	return route;
+}
+
+/**
+ * Destroy a route_entry_t object
+ */
+static void route_entry_destroy(route_entry_t *this)
+{
+	free(this->if_name);
+	DESTROY_IF(this->src_ip);
+	DESTROY_IF(this->gateway);
+	chunk_free(&this->dst_net);
+	free(this);
+}
+
+/**
+ * Hash a route_entry_t object
+ */
+static u_int route_entry_hash(route_entry_t *this)
+{
+	return chunk_hash_inc(chunk_from_thing(this->prefixlen),
+						  chunk_hash(this->dst_net));
+}
+
+/**
+ * Compare two route_entry_t objects
+ */
+static bool route_entry_equals(route_entry_t *a, route_entry_t *b)
+{
+	if (a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
+		a->src_ip->ip_equals(a->src_ip, b->src_ip) &&
+		chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen)
+	{
+		return (!a->gateway && !b->gateway) || (a->gateway && b->gateway &&
+					a->gateway->ip_equals(a->gateway, b->gateway));
+	}
+	return FALSE;
+}
+
+typedef struct net_change_t net_change_t;
+
+/**
+ * Queued network changes
+ */
+struct net_change_t {
+	/** Name of the interface that got activated (or an IP appeared on) */
+	char *if_name;
+};
+
+/**
+ * Destroy a net_change_t object
+ */
+static void net_change_destroy(net_change_t *this)
+{
+	free(this->if_name);
+	free(this);
+}
+
+/**
+ * Hash a net_change_t object
+ */
+static u_int net_change_hash(net_change_t *this)
+{
+	return chunk_hash(chunk_create(this->if_name, strlen(this->if_name)));
+}
+
+/**
+ * Compare two net_change_t objects
+ */
+static bool net_change_equals(net_change_t *a, net_change_t *b)
+{
+	return streq(a->if_name, b->if_name);
+}
+
+typedef struct private_kernel_netlink_net_t private_kernel_netlink_net_t;
+
+/**
+ * Private variables and functions of kernel_netlink_net class.
+ */
+struct private_kernel_netlink_net_t {
+	/**
+	 * Public part of the kernel_netlink_net_t object.
+	 */
+	kernel_netlink_net_t public;
+
+	/**
+	 * lock to access various lists and maps
+	 */
+	rwlock_t *lock;
+
+	/**
+	 * condition variable to signal virtual IP add/removal
+	 */
+	rwlock_condvar_t *condvar;
+
+	/**
+	 * Cached list of interfaces and its addresses (iface_entry_t)
+	 */
+	linked_list_t *ifaces;
+
+	/**
+	 * Map for IP addresses to iface_entry_t objects (addr_map_entry_t)
+	 */
+	hashtable_t *addrs;
+
+	/**
+	 * Map for virtual IP addresses to iface_entry_t objects (addr_map_entry_t)
+	 */
+	hashtable_t *vips;
+
+	/**
+	 * netlink rt socket (routing)
+	 */
+	netlink_socket_t *socket;
+
+	/**
+	 * Netlink rt socket to receive address change events
+	 */
+	int socket_events;
+
+	/**
+	 * earliest time of the next roam event
+	 */
+	timeval_t next_roam;
+
+	/**
+	 * roam event due to address change
+	 */
+	bool roam_address;
+
+	/**
+	 * lock to check and update roam event time
+	 */
+	spinlock_t *roam_lock;
+
+	/**
+	 * routing table to install routes
+	 */
+	int routing_table;
+
+	/**
+	 * priority of used routing table
+	 */
+	int routing_table_prio;
+
+	/**
+	 * installed routes
+	 */
+	hashtable_t *routes;
+
+	/**
+	 * mutex for routes
+	 */
+	mutex_t *routes_lock;
+
+	/**
+	 * interface changes which may trigger route reinstallation
+	 */
+	hashtable_t *net_changes;
+
+	/**
+	 * mutex for route reinstallation triggers
+	 */
+	mutex_t *net_changes_lock;
+
+	/**
+	 * time of last route reinstallation
+	 */
+	timeval_t last_route_reinstall;
+
+	/**
+	 * whether to react to RTM_NEWROUTE or RTM_DELROUTE events
+	 */
+	bool process_route;
+
+	/**
+	 * whether to trigger roam events
+	 */
+	bool roam_events;
+
+	/**
+	 * whether to actually install virtual IPs
+	 */
+	bool install_virtual_ip;
+
+	/**
+	 * the name of the interface virtual IP addresses are installed on
+	 */
+	char *install_virtual_ip_on;
+
+	/**
+	 * whether preferred source addresses can be specified for IPv6 routes
+	 */
+	bool rta_prefsrc_for_ipv6;
+
+	/**
+	 * whether marks can be used in route lookups
+	 */
+	bool rta_mark;
+
+	/**
+	 * the mark excluded from the routing rule used for virtual IPs
+	 */
+	mark_t routing_mark;
+
+	/**
+	 * whether to prefer temporary IPv6 addresses over public ones
+	 */
+	bool prefer_temporary_addrs;
+
+	/**
+	 * list with routing tables to be excluded from route lookup
+	 */
+	linked_list_t *rt_exclude;
+
+	/**
+	 * MTU to set on installed routes
+	 */
+	u_int32_t mtu;
+
+	/**
+	 * MSS to set on installed routes
+	 */
+	u_int32_t mss;
+};
+
+/**
+ * Forward declaration
+ */
+static status_t manage_srcroute(private_kernel_netlink_net_t *this,
+								int nlmsg_type, int flags, chunk_t dst_net,
+								u_int8_t prefixlen, host_t *gateway,
+								host_t *src_ip, char *if_name);
+
+/**
+ * Clear the queued network changes.
+ */
+static void net_changes_clear(private_kernel_netlink_net_t *this)
+{
+	enumerator_t *enumerator;
+	net_change_t *change;
+
+	enumerator = this->net_changes->create_enumerator(this->net_changes);
+	while (enumerator->enumerate(enumerator, NULL, (void**)&change))
+	{
+		this->net_changes->remove_at(this->net_changes, enumerator);
+		net_change_destroy(change);
+	}
+	enumerator->destroy(enumerator);
+}
+
+/**
+ * Act upon queued network changes.
+ */
+static job_requeue_t reinstall_routes(private_kernel_netlink_net_t *this)
+{
+	enumerator_t *enumerator;
+	route_entry_t *route;
+
+	this->net_changes_lock->lock(this->net_changes_lock);
+	this->routes_lock->lock(this->routes_lock);
+
+	enumerator = this->routes->create_enumerator(this->routes);
+	while (enumerator->enumerate(enumerator, NULL, (void**)&route))
+	{
+		net_change_t *change, lookup = {
+			.if_name = route->if_name,
+		};
+		/* check if a change for the outgoing interface is queued */
+		change = this->net_changes->get(this->net_changes, &lookup);
+		if (!change)
+		{	/* in case src_ip is not on the outgoing interface */
+			if (this->public.interface.get_interface(&this->public.interface,
+												route->src_ip, &lookup.if_name))
+			{
+				if (!streq(lookup.if_name, route->if_name))
+				{
+					change = this->net_changes->get(this->net_changes, &lookup);
+				}
+				free(lookup.if_name);
+			}
+		}
+		if (change)
+		{
+			manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL,
+							route->dst_net, route->prefixlen, route->gateway,
+							route->src_ip, route->if_name);
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->routes_lock->unlock(this->routes_lock);
+
+	net_changes_clear(this);
+	this->net_changes_lock->unlock(this->net_changes_lock);
+	return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Queue route reinstallation caused by network changes for a given interface.
+ *
+ * The route reinstallation is delayed for a while and only done once for
+ * several calls during this delay, in order to avoid doing it too often.
+ * The interface name is freed.
+ */
+static void queue_route_reinstall(private_kernel_netlink_net_t *this,
+								  char *if_name)
+{
+	net_change_t *update, *found;
+	timeval_t now;
+	job_t *job;
+
+	INIT(update,
+		.if_name = if_name
+	);
+
+	this->net_changes_lock->lock(this->net_changes_lock);
+	found = this->net_changes->put(this->net_changes, update, update);
+	if (found)
+	{
+		net_change_destroy(found);
+	}
+	time_monotonic(&now);
+	if (timercmp(&now, &this->last_route_reinstall, >))
+	{
+		timeval_add_ms(&now, ROUTE_DELAY);
+		this->last_route_reinstall = now;
+
+		job = (job_t*)callback_job_create((callback_job_cb_t)reinstall_routes,
+										  this, NULL, NULL);
+		lib->scheduler->schedule_job_ms(lib->scheduler, job, ROUTE_DELAY);
+	}
+	this->net_changes_lock->unlock(this->net_changes_lock);
+}
+
+/**
+ * check if the given IP is known as virtual IP and currently installed
+ *
+ * this function will also return TRUE if the virtual IP entry disappeared.
+ * in that case the returned entry will be NULL.
+ *
+ * this->lock must be held when calling this function
+ */
+static bool is_vip_installed_or_gone(private_kernel_netlink_net_t *this,
+									 host_t *ip, addr_map_entry_t **entry)
+{
+	addr_map_entry_t lookup = {
+		.ip = ip,
+	};
+
+	*entry = this->vips->get_match(this->vips, &lookup,
+								  (void*)addr_map_entry_match);
+	if (*entry == NULL)
+	{	/* the virtual IP disappeared */
+		return TRUE;
+	}
+	return (*entry)->addr->installed;
+}
+
+/**
+ * check if the given IP is known as virtual IP
+ *
+ * this->lock must be held when calling this function
+ */
+static bool is_known_vip(private_kernel_netlink_net_t *this, host_t *ip)
+{
+	addr_map_entry_t lookup = {
+		.ip = ip,
+	};
+
+	return this->vips->get_match(this->vips, &lookup,
+								(void*)addr_map_entry_match) != NULL;
+}
+
+/**
+ * Add an address map entry
+ */
+static void addr_map_entry_add(hashtable_t *map, addr_entry_t *addr,
+							   iface_entry_t *iface)
+{
+	addr_map_entry_t *entry;
+
+	INIT(entry,
+		.ip = addr->ip,
+		.addr = addr,
+		.iface = iface,
+	);
+	entry = map->put(map, entry, entry);
+	free(entry);
+}
+
+/**
+ * Remove an address map entry
+ */
+static void addr_map_entry_remove(hashtable_t *map, addr_entry_t *addr,
+								  iface_entry_t *iface)
+{
+	addr_map_entry_t *entry, lookup = {
+		.ip = addr->ip,
+		.addr = addr,
+		.iface = iface,
+	};
+
+	entry = map->remove(map, &lookup);
+	free(entry);
+}
+
+/**
+ * Determine the type or scope of the given unicast IP address.  This is not
+ * the same thing returned in rtm_scope/ifa_scope.
+ *
+ * We use return values as defined in RFC 6724 (referring to RFC 4291).
+ */
+static u_char get_scope(host_t *ip)
+{
+	chunk_t addr;
+
+	addr = ip->get_address(ip);
+	switch (addr.len)
+	{
+		case 4:
+			/* we use the mapping defined in RFC 6724, 3.2 */
+			if (addr.ptr[0] == 127)
+			{	/* link-local, same as the IPv6 loopback address */
+				return 2;
+			}
+			if (addr.ptr[0] == 169 && addr.ptr[1] == 254)
+			{	/* link-local */
+				return 2;
+			}
+			break;
+		case 16:
+			if (IN6_IS_ADDR_LOOPBACK((struct in6_addr*)addr.ptr))
+			{	/* link-local, according to RFC 4291, 2.5.3 */
+				return 2;
+			}
+			if (IN6_IS_ADDR_LINKLOCAL((struct in6_addr*)addr.ptr))
+			{
+				return 2;
+			}
+			if (IN6_IS_ADDR_SITELOCAL((struct in6_addr*)addr.ptr))
+			{	/* deprecated, according to RFC 4291, 2.5.7 */
+				return 5;
+			}
+			break;
+		default:
+			break;
+	}
+	/* global */
+	return 14;
+}
+
+/**
+ * Returns the length of the common prefix in bits up to the length of a's
+ * prefix, defined by RFC 6724 as the portion of the address not including the
+ * interface ID, which is 64-bit for most unicast addresses (see RFC 4291).
+ */
+static u_char common_prefix(host_t *a, host_t *b)
+{
+	chunk_t aa, ba;
+	u_char byte, bits = 0, match;
+
+	aa = a->get_address(a);
+	ba = b->get_address(b);
+	for (byte = 0; byte < 8; byte++)
+	{
+		if (aa.ptr[byte] != ba.ptr[byte])
+		{
+			match = aa.ptr[byte] ^ ba.ptr[byte];
+			for (bits = 8; match; match >>= 1)
+			{
+				bits--;
+			}
+			break;
+		}
+	}
+	return byte * 8 + bits;
+}
+
+/**
+ * Compare two IP addresses and return TRUE if the second address is the better
+ * choice of the two to reach the destination.
+ * For IPv6 we approximately follow RFC 6724.
+ */
+static bool is_address_better(private_kernel_netlink_net_t *this,
+							  addr_entry_t *a, addr_entry_t *b, host_t *d)
+{
+	u_char sa, sb, sd, pa, pb;
+
+	/* rule 2: prefer appropriate scope */
+	if (d)
+	{
+		sa = get_scope(a->ip);
+		sb = get_scope(b->ip);
+		sd = get_scope(d);
+		if (sa < sb)
+		{
+			return sa < sd;
+		}
+		else if (sb < sa)
+		{
+			return sb >= sd;
+		}
+	}
+	if (a->ip->get_family(a->ip) == AF_INET)
+	{	/* stop here for IPv4, default to addresses found earlier */
+		return FALSE;
+	}
+	/* rule 3: avoid deprecated addresses (RFC 4862) */
+	if ((a->flags & IFA_F_DEPRECATED) != (b->flags & IFA_F_DEPRECATED))
+	{
+		return a->flags & IFA_F_DEPRECATED;
+	}
+	/* rule 4 is not applicable as we don't know if an address is a home or
+	 * care-of addresses.
+	 * rule 5 does not apply as we only compare addresses from one interface
+	 * rule 6 requires a policy table (optionally configurable) to match
+	 * configurable labels
+	 */
+	/* rule 7: prefer temporary addresses (WE REVERSE THIS BY DEFAULT!) */
+	if ((a->flags & IFA_F_TEMPORARY) != (b->flags & IFA_F_TEMPORARY))
+	{
+		if (this->prefer_temporary_addrs)
+		{
+			return b->flags & IFA_F_TEMPORARY;
+		}
+		return a->flags & IFA_F_TEMPORARY;
+	}
+	/* rule 8: use longest matching prefix */
+	if (d)
+	{
+		pa = common_prefix(a->ip, d);
+		pb = common_prefix(b->ip, d);
+		if (pa != pb)
+		{
+			return pb > pa;
+		}
+	}
+	/* default to addresses found earlier */
+	return FALSE;
+}
+
+/**
+ * Get a non-virtual IP address on the given interface.
+ *
+ * If a candidate address is given, we first search for that address and if not
+ * found return the address as above.
+ * Returned host is a clone, has to be freed by caller.
+ *
+ * this->lock must be held when calling this function.
+ */
+static host_t *get_interface_address(private_kernel_netlink_net_t *this,
+									 int ifindex, int family, host_t *dest,
+									 host_t *candidate)
+{
+	iface_entry_t *iface;
+	enumerator_t *addrs;
+	addr_entry_t *addr, *best = NULL;
+
+	if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index,
+								 (void**)&iface, &ifindex) == SUCCESS)
+	{
+		if (iface->usable)
+		{	/* only use interfaces not excluded by config */
+			addrs = iface->addrs->create_enumerator(iface->addrs);
+			while (addrs->enumerate(addrs, &addr))
+			{
+				if (addr->refcount ||
+					addr->ip->get_family(addr->ip) != family)
+				{	/* ignore virtual IP addresses and ensure family matches */
+					continue;
+				}
+				if (candidate && candidate->ip_equals(candidate, addr->ip))
+				{	/* stop if we find the candidate */
+					best = addr;
+					break;
+				}
+				else if (!best || is_address_better(this, best, addr, dest))
+				{
+					best = addr;
+				}
+			}
+			addrs->destroy(addrs);
+		}
+	}
+	return best ? best->ip->clone(best->ip) : NULL;
+}
+
+/**
+ * callback function that raises the delayed roam event
+ */
+static job_requeue_t roam_event(private_kernel_netlink_net_t *this)
+{
+	bool address;
+
+	this->roam_lock->lock(this->roam_lock);
+	address = this->roam_address;
+	this->roam_address = FALSE;
+	this->roam_lock->unlock(this->roam_lock);
+	charon->kernel->roam(charon->kernel, address);
+	return JOB_REQUEUE_NONE;
+}
+
+/**
+ * fire a roaming event. we delay it for a bit and fire only one event
+ * for multiple calls. otherwise we would create too many events.
+ */
+static void fire_roam_event(private_kernel_netlink_net_t *this, bool address)
+{
+	timeval_t now;
+	job_t *job;
+
+	if (!this->roam_events)
+	{
+		return;
+	}
+
+	time_monotonic(&now);
+	this->roam_lock->lock(this->roam_lock);
+	this->roam_address |= address;
+	if (!timercmp(&now, &this->next_roam, >))
+	{
+		this->roam_lock->unlock(this->roam_lock);
+		return;
+	}
+	timeval_add_ms(&now, ROAM_DELAY);
+	this->next_roam = now;
+	this->roam_lock->unlock(this->roam_lock);
+
+	job = (job_t*)callback_job_create((callback_job_cb_t)roam_event,
+									  this, NULL, NULL);
+	lib->scheduler->schedule_job_ms(lib->scheduler, job, ROAM_DELAY);
+}
+
+/**
+ * check if an interface with a given index is up and usable
+ *
+ * this->lock must be locked when calling this function
+ */
+static bool is_interface_up_and_usable(private_kernel_netlink_net_t *this,
+									   int index)
+{
+	iface_entry_t *iface;
+
+	if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index,
+								 (void**)&iface, &index) == SUCCESS)
+	{
+		return iface_entry_up_and_usable(iface);
+	}
+	return FALSE;
+}
+
+/**
+ * unregister the current addr_entry_t from the hashtable it is stored in
+ *
+ * this->lock must be locked when calling this function
+ */
+static void addr_entry_unregister(addr_entry_t *addr, iface_entry_t *iface,
+								  private_kernel_netlink_net_t *this)
+{
+	if (addr->refcount)
+	{
+		addr_map_entry_remove(this->vips, addr, iface);
+		this->condvar->broadcast(this->condvar);
+		return;
+	}
+	addr_map_entry_remove(this->addrs, addr, iface);
+}
+
+/**
+ * process RTM_NEWLINK/RTM_DELLINK from kernel
+ */
+static void process_link(private_kernel_netlink_net_t *this,
+						 struct nlmsghdr *hdr, bool event)
+{
+	struct ifinfomsg* msg = NLMSG_DATA(hdr);
+	struct rtattr *rta = IFLA_RTA(msg);
+	size_t rtasize = IFLA_PAYLOAD (hdr);
+	enumerator_t *enumerator;
+	iface_entry_t *current, *entry = NULL;
+	char *name = NULL;
+	bool update = FALSE, update_routes = FALSE;
+
+	while (RTA_OK(rta, rtasize))
+	{
+		switch (rta->rta_type)
+		{
+			case IFLA_IFNAME:
+				name = RTA_DATA(rta);
+				break;
+		}
+		rta = RTA_NEXT(rta, rtasize);
+	}
+	if (!name)
+	{
+		name = "(unknown)";
+	}
+
+	this->lock->write_lock(this->lock);
+	switch (hdr->nlmsg_type)
+	{
+		case RTM_NEWLINK:
+		{
+			if (this->ifaces->find_first(this->ifaces,
+									(void*)iface_entry_by_index, (void**)&entry,
+									&msg->ifi_index) != SUCCESS)
+			{
+				INIT(entry,
+					.ifindex = msg->ifi_index,
+					.addrs = linked_list_create(),
+					.usable = charon->kernel->is_interface_usable(
+														charon->kernel, name),
+				);
+				this->ifaces->insert_last(this->ifaces, entry);
+			}
+			strncpy(entry->ifname, name, IFNAMSIZ);
+			entry->ifname[IFNAMSIZ-1] = '\0';
+			if (event && entry->usable)
+			{
+				if (!(entry->flags & IFF_UP) && (msg->ifi_flags & IFF_UP))
+				{
+					update = update_routes = TRUE;
+					DBG1(DBG_KNL, "interface %s activated", name);
+				}
+				if ((entry->flags & IFF_UP) && !(msg->ifi_flags & IFF_UP))
+				{
+					update = TRUE;
+					DBG1(DBG_KNL, "interface %s deactivated", name);
+				}
+			}
+			entry->flags = msg->ifi_flags;
+			break;
+		}
+		case RTM_DELLINK:
+		{
+			enumerator = this->ifaces->create_enumerator(this->ifaces);
+			while (enumerator->enumerate(enumerator, &current))
+			{
+				if (current->ifindex == msg->ifi_index)
+				{
+					if (event && current->usable)
+					{
+						update = TRUE;
+						DBG1(DBG_KNL, "interface %s deleted", current->ifname);
+					}
+					/* TODO: move virtual IPs installed on this interface to
+					 * another interface? */
+					this->ifaces->remove_at(this->ifaces, enumerator);
+					current->addrs->invoke_function(current->addrs,
+								(void*)addr_entry_unregister, current, this);
+					iface_entry_destroy(current);
+					break;
+				}
+			}
+			enumerator->destroy(enumerator);
+			break;
+		}
+	}
+	this->lock->unlock(this->lock);
+
+	if (update_routes && event)
+	{
+		queue_route_reinstall(this, strdup(name));
+	}
+
+	if (update && event)
+	{
+		fire_roam_event(this, TRUE);
+	}
+}
+
+/**
+ * process RTM_NEWADDR/RTM_DELADDR from kernel
+ */
+static void process_addr(private_kernel_netlink_net_t *this,
+						 struct nlmsghdr *hdr, bool event)
+{
+	struct ifaddrmsg* msg = NLMSG_DATA(hdr);
+	struct rtattr *rta = IFA_RTA(msg);
+	size_t rtasize = IFA_PAYLOAD (hdr);
+	host_t *host = NULL;
+	iface_entry_t *iface;
+	chunk_t local = chunk_empty, address = chunk_empty;
+	char *route_ifname = NULL;
+	bool update = FALSE, found = FALSE, changed = FALSE;
+
+	while (RTA_OK(rta, rtasize))
+	{
+		switch (rta->rta_type)
+		{
+			case IFA_LOCAL:
+				local.ptr = RTA_DATA(rta);
+				local.len = RTA_PAYLOAD(rta);
+				break;
+			case IFA_ADDRESS:
+				address.ptr = RTA_DATA(rta);
+				address.len = RTA_PAYLOAD(rta);
+				break;
+		}
+		rta = RTA_NEXT(rta, rtasize);
+	}
+
+	/* For PPP interfaces, we need the IFA_LOCAL address,
+	 * IFA_ADDRESS is the peers address. But IFA_LOCAL is
+	 * not included in all cases (IPv6?), so fallback to IFA_ADDRESS. */
+	if (local.ptr)
+	{
+		host = host_create_from_chunk(msg->ifa_family, local, 0);
+	}
+	else if (address.ptr)
+	{
+		host = host_create_from_chunk(msg->ifa_family, address, 0);
+	}
+
+	if (host == NULL)
+	{	/* bad family? */
+		return;
+	}
+
+	this->lock->write_lock(this->lock);
+	if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index,
+								 (void**)&iface, &msg->ifa_index) == SUCCESS)
+	{
+		addr_map_entry_t *entry, lookup = {
+			.ip = host,
+			.iface = iface,
+		};
+		addr_entry_t *addr;
+
+		entry = this->vips->get(this->vips, &lookup);
+		if (entry)
+		{
+			if (hdr->nlmsg_type == RTM_NEWADDR)
+			{	/* mark as installed and signal waiting threads */
+				entry->addr->installed = TRUE;
+			}
+			else
+			{	/* the address was already marked as uninstalled */
+				addr = entry->addr;
+				iface->addrs->remove(iface->addrs, addr, NULL);
+				addr_map_entry_remove(this->vips, addr, iface);
+				addr_entry_destroy(addr);
+			}
+			/* no roam events etc. for virtual IPs */
+			this->condvar->broadcast(this->condvar);
+			this->lock->unlock(this->lock);
+			host->destroy(host);
+			return;
+		}
+		entry = this->addrs->get(this->addrs, &lookup);
+		if (entry)
+		{
+			if (hdr->nlmsg_type == RTM_DELADDR)
+			{
+				found = TRUE;
+				addr = entry->addr;
+				iface->addrs->remove(iface->addrs, addr, NULL);
+				if (iface->usable)
+				{
+					changed = TRUE;
+					DBG1(DBG_KNL, "%H disappeared from %s", host,
+						 iface->ifname);
+				}
+				addr_map_entry_remove(this->addrs, addr, iface);
+				addr_entry_destroy(addr);
+			}
+		}
+		else
+		{
+			if (hdr->nlmsg_type == RTM_NEWADDR)
+			{
+				found = TRUE;
+				changed = TRUE;
+				route_ifname = strdup(iface->ifname);
+				INIT(addr,
+					.ip = host->clone(host),
+					.flags = msg->ifa_flags,
+					.scope = msg->ifa_scope,
+				);
+				iface->addrs->insert_last(iface->addrs, addr);
+				addr_map_entry_add(this->addrs, addr, iface);
+				if (event && iface->usable)
+				{
+					DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
+				}
+			}
+		}
+		if (found && (iface->flags & IFF_UP))
+		{
+			update = TRUE;
+		}
+		if (!iface->usable)
+		{	/* ignore events for interfaces excluded by config */
+			update = changed = FALSE;
+		}
+	}
+	this->lock->unlock(this->lock);
+
+	if (update && event && route_ifname)
+	{
+		queue_route_reinstall(this, route_ifname);
+	}
+	else
+	{
+		free(route_ifname);
+	}
+	host->destroy(host);
+
+	/* send an update to all IKE_SAs */
+	if (update && event && changed)
+	{
+		fire_roam_event(this, TRUE);
+	}
+}
+
+/**
+ * process RTM_NEWROUTE and RTM_DELROUTE from kernel
+ */
+static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *hdr)
+{
+	struct rtmsg* msg = NLMSG_DATA(hdr);
+	struct rtattr *rta = RTM_RTA(msg);
+	size_t rtasize = RTM_PAYLOAD(hdr);
+	u_int32_t rta_oif = 0;
+	host_t *host = NULL;
+
+	/* ignore routes added by us or in the local routing table (local addrs) */
+	if (msg->rtm_table && (msg->rtm_table == this->routing_table ||
+						   msg->rtm_table == RT_TABLE_LOCAL))
+	{
+		return;
+	}
+	else if (msg->rtm_flags & RTM_F_CLONED)
+	{	/* ignore cached routes, seem to be created a lot for IPv6 */
+		return;
+	}
+
+	while (RTA_OK(rta, rtasize))
+	{
+		switch (rta->rta_type)
+		{
+			case RTA_PREFSRC:
+				DESTROY_IF(host);
+				host = host_create_from_chunk(msg->rtm_family,
+							chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)), 0);
+				break;
+			case RTA_OIF:
+				if (RTA_PAYLOAD(rta) == sizeof(rta_oif))
+				{
+					rta_oif = *(u_int32_t*)RTA_DATA(rta);
+				}
+				break;
+		}
+		rta = RTA_NEXT(rta, rtasize);
+	}
+	this->lock->read_lock(this->lock);
+	if (rta_oif && !is_interface_up_and_usable(this, rta_oif))
+	{	/* ignore route changes for interfaces that are ignored or down */
+		this->lock->unlock(this->lock);
+		DESTROY_IF(host);
+		return;
+	}
+	if (!host && rta_oif)
+	{
+		host = get_interface_address(this, rta_oif, msg->rtm_family,
+									 NULL, NULL);
+	}
+	if (!host || is_known_vip(this, host))
+	{	/* ignore routes added for virtual IPs */
+		this->lock->unlock(this->lock);
+		DESTROY_IF(host);
+		return;
+	}
+	this->lock->unlock(this->lock);
+	fire_roam_event(this, FALSE);
+	host->destroy(host);
+}
+
+/**
+ * Receives events from kernel
+ */
+static bool receive_events(private_kernel_netlink_net_t *this, int fd,
+						   watcher_event_t event)
+{
+	char response[1536];
+	struct nlmsghdr *hdr = (struct nlmsghdr*)response;
+	struct sockaddr_nl addr;
+	socklen_t addr_len = sizeof(addr);
+	int len;
+
+	len = recvfrom(this->socket_events, response, sizeof(response),
+				   MSG_DONTWAIT, (struct sockaddr*)&addr, &addr_len);
+	if (len < 0)
+	{
+		switch (errno)
+		{
+			case EINTR:
+				/* interrupted, try again */
+				return TRUE;
+			case EAGAIN:
+				/* no data ready, select again */
+				return TRUE;
+			default:
+				DBG1(DBG_KNL, "unable to receive from rt event socket");
+				sleep(1);
+				return TRUE;
+		}
+	}
+
+	if (addr.nl_pid != 0)
+	{	/* not from kernel. not interested, try another one */
+		return TRUE;
+	}
+
+	while (NLMSG_OK(hdr, len))
+	{
+		/* looks good so far, dispatch netlink message */
+		switch (hdr->nlmsg_type)
+		{
+			case RTM_NEWADDR:
+			case RTM_DELADDR:
+				process_addr(this, hdr, TRUE);
+				break;
+			case RTM_NEWLINK:
+			case RTM_DELLINK:
+				process_link(this, hdr, TRUE);
+				break;
+			case RTM_NEWROUTE:
+			case RTM_DELROUTE:
+				if (this->process_route)
+				{
+					process_route(this, hdr);
+				}
+				break;
+			default:
+				break;
+		}
+		hdr = NLMSG_NEXT(hdr, len);
+	}
+	return TRUE;
+}
+
+/** enumerator over addresses */
+typedef struct {
+	private_kernel_netlink_net_t* this;
+	/** which addresses to enumerate */
+	kernel_address_type_t which;
+} address_enumerator_t;
+
+/**
+ * cleanup function for address enumerator
+ */
+static void address_enumerator_destroy(address_enumerator_t *data)
+{
+	data->this->lock->unlock(data->this->lock);
+	free(data);
+}
+
+/**
+ * filter for addresses
+ */
+static bool filter_addresses(address_enumerator_t *data,
+							 addr_entry_t** in, host_t** out)
+{
+	if (!(data->which & ADDR_TYPE_VIRTUAL) && (*in)->refcount)
+	{	/* skip virtual interfaces added by us */
+		return FALSE;
+	}
+	if (!(data->which & ADDR_TYPE_REGULAR) && !(*in)->refcount)
+	{	/* address is regular, but not requested */
+		return FALSE;
+	}
+	if ((*in)->scope >= RT_SCOPE_LINK)
+	{	/* skip addresses with a unusable scope */
+		return FALSE;
+	}
+	*out = (*in)->ip;
+	return TRUE;
+}
+
+/**
+ * enumerator constructor for interfaces
+ */
+static enumerator_t *create_iface_enumerator(iface_entry_t *iface,
+											 address_enumerator_t *data)
+{
+	return enumerator_create_filter(
+				iface->addrs->create_enumerator(iface->addrs),
+				(void*)filter_addresses, data, NULL);
+}
+
+/**
+ * filter for interfaces
+ */
+static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in,
+							  iface_entry_t** out)
+{
+	if (!(data->which & ADDR_TYPE_IGNORED) && !(*in)->usable)
+	{	/* skip interfaces excluded by config */
+		return FALSE;
+	}
+	if (!(data->which & ADDR_TYPE_LOOPBACK) && ((*in)->flags & IFF_LOOPBACK))
+	{	/* ignore loopback devices */
+		return FALSE;
+	}
+	if (!(data->which & ADDR_TYPE_DOWN) && !((*in)->flags & IFF_UP))
+	{	/* skip interfaces not up */
+		return FALSE;
+	}
+	*out = *in;
+	return TRUE;
+}
+
+METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
+	private_kernel_netlink_net_t *this, kernel_address_type_t which)
+{
+	address_enumerator_t *data;
+
+	INIT(data,
+		.this = this,
+		.which = which,
+	);
+
+	this->lock->read_lock(this->lock);
+	return enumerator_create_nested(
+				enumerator_create_filter(
+					this->ifaces->create_enumerator(this->ifaces),
+					(void*)filter_interfaces, data, NULL),
+				(void*)create_iface_enumerator, data,
+				(void*)address_enumerator_destroy);
+}
+
+METHOD(kernel_net_t, get_interface_name, bool,
+	private_kernel_netlink_net_t *this, host_t* ip, char **name)
+{
+	addr_map_entry_t *entry, lookup = {
+		.ip = ip,
+	};
+
+	if (ip->is_anyaddr(ip))
+	{
+		return FALSE;
+	}
+	this->lock->read_lock(this->lock);
+	/* first try to find it on an up and usable interface */
+	entry = this->addrs->get_match(this->addrs, &lookup,
+								  (void*)addr_map_entry_match_up_and_usable);
+	if (entry)
+	{
+		if (name)
+		{
+			*name = strdup(entry->iface->ifname);
+			DBG2(DBG_KNL, "%H is on interface %s", ip, *name);
+		}
+		this->lock->unlock(this->lock);
+		return TRUE;
+	}
+	/* in a second step, consider virtual IPs installed by us */
+	entry = this->vips->get_match(this->vips, &lookup,
+								  (void*)addr_map_entry_match_up_and_usable);
+	if (entry)
+	{
+		if (name)
+		{
+			*name = strdup(entry->iface->ifname);
+			DBG2(DBG_KNL, "virtual IP %H is on interface %s", ip, *name);
+		}
+		this->lock->unlock(this->lock);
+		return TRUE;
+	}
+	/* maybe it is installed on an ignored interface */
+	entry = this->addrs->get_match(this->addrs, &lookup,
+								  (void*)addr_map_entry_match_up);
+	if (!entry)
+	{
+		DBG2(DBG_KNL, "%H is not a local address or the interface is down", ip);
+	}
+	this->lock->unlock(this->lock);
+	return FALSE;
+}
+
+/**
+ * get the index of an interface by name
+ */
+static int get_interface_index(private_kernel_netlink_net_t *this, char* name)
+{
+	iface_entry_t *iface;
+	int ifindex = 0;
+
+	DBG2(DBG_KNL, "getting iface index for %s", name);
+
+	this->lock->read_lock(this->lock);
+	if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_name,
+								(void**)&iface, name) == SUCCESS)
+	{
+		ifindex = iface->ifindex;
+	}
+	this->lock->unlock(this->lock);
+
+	if (ifindex == 0)
+	{
+		DBG1(DBG_KNL, "unable to get interface index for %s", name);
+	}
+	return ifindex;
+}
+
+/**
+ * check if an address or net (addr with prefix net bits) is in
+ * subnet (net with net_len net bits)
+ */
+static bool addr_in_subnet(chunk_t addr, int prefix, chunk_t net, int net_len)
+{
+	static const u_char mask[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
+	int byte = 0;
+
+	if (net_len == 0)
+	{	/* any address matches a /0 network */
+		return TRUE;
+	}
+	if (addr.len != net.len || net_len > 8 * net.len || prefix < net_len)
+	{
+		return FALSE;
+	}
+	/* scan through all bytes in network order */
+	while (net_len > 0)
+	{
+		if (net_len < 8)
+		{
+			return (mask[net_len] & addr.ptr[byte]) == (mask[net_len] & net.ptr[byte]);
+		}
+		else
+		{
+			if (addr.ptr[byte] != net.ptr[byte])
+			{
+				return FALSE;
+			}
+			byte++;
+			net_len -= 8;
+		}
+	}
+	return TRUE;
+}
+
+/**
+ * Store information about a route retrieved via RTNETLINK
+ */
+typedef struct {
+	chunk_t gtw;
+	chunk_t src;
+	chunk_t dst;
+	host_t *src_host;
+	u_int8_t dst_len;
+	u_int32_t table;
+	u_int32_t oif;
+	u_int32_t priority;
+} rt_entry_t;
+
+/**
+ * Free a route entry
+ */
+static void rt_entry_destroy(rt_entry_t *this)
+{
+	DESTROY_IF(this->src_host);
+	free(this);
+}
+
+/**
+ * Check if the route received with RTM_NEWROUTE is usable based on its type.
+ */
+static bool route_usable(struct nlmsghdr *hdr)
+{
+	struct rtmsg *msg;
+
+	msg = NLMSG_DATA(hdr);
+	switch (msg->rtm_type)
+	{
+		case RTN_BLACKHOLE:
+		case RTN_UNREACHABLE:
+		case RTN_PROHIBIT:
+		case RTN_THROW:
+			return FALSE;
+		default:
+			return TRUE;
+	}
+}
+
+/**
+ * Parse route received with RTM_NEWROUTE. The given rt_entry_t object will be
+ * reused if not NULL.
+ *
+ * Returned chunks point to internal data of the Netlink message.
+ */
+static rt_entry_t *parse_route(struct nlmsghdr *hdr, rt_entry_t *route)
+{
+	struct rtattr *rta;
+	struct rtmsg *msg;
+	size_t rtasize;
+
+	msg = NLMSG_DATA(hdr);
+	rta = RTM_RTA(msg);
+	rtasize = RTM_PAYLOAD(hdr);
+
+	if (route)
+	{
+		route->gtw = chunk_empty;
+		route->src = chunk_empty;
+		route->dst = chunk_empty;
+		route->dst_len = msg->rtm_dst_len;
+		route->table = msg->rtm_table;
+		route->oif = 0;
+		route->priority = 0;
+	}
+	else
+	{
+		INIT(route,
+			.dst_len = msg->rtm_dst_len,
+			.table = msg->rtm_table,
+		);
+	}
+
+	while (RTA_OK(rta, rtasize))
+	{
+		switch (rta->rta_type)
+		{
+			case RTA_PREFSRC:
+				route->src = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
+				break;
+			case RTA_GATEWAY:
+				route->gtw = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
+				break;
+			case RTA_DST:
+				route->dst = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
+				break;
+			case RTA_OIF:
+				if (RTA_PAYLOAD(rta) == sizeof(route->oif))
+				{
+					route->oif = *(u_int32_t*)RTA_DATA(rta);
+				}
+				break;
+			case RTA_PRIORITY:
+				if (RTA_PAYLOAD(rta) == sizeof(route->priority))
+				{
+					route->priority = *(u_int32_t*)RTA_DATA(rta);
+				}
+				break;
+#ifdef HAVE_RTA_TABLE
+			case RTA_TABLE:
+				if (RTA_PAYLOAD(rta) == sizeof(route->table))
+				{
+					route->table = *(u_int32_t*)RTA_DATA(rta);
+				}
+				break;
+#endif /* HAVE_RTA_TABLE*/
+		}
+		rta = RTA_NEXT(rta, rtasize);
+	}
+	return route;
+}
+
+/**
+ * Get a route: If "nexthop", the nexthop is returned. source addr otherwise.
+ */
+static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
+						 int prefix, bool nexthop, host_t *candidate,
+						 u_int recursion)
+{
+	netlink_buf_t request;
+	struct nlmsghdr *hdr, *out, *current;
+	struct rtmsg *msg;
+	chunk_t chunk;
+	size_t len;
+	linked_list_t *routes;
+	rt_entry_t *route = NULL, *best = NULL;
+	enumerator_t *enumerator;
+	host_t *addr = NULL;
+	bool match_net;
+	int family;
+
+	if (recursion > MAX_ROUTE_RECURSION)
+	{
+		return NULL;
+	}
+	chunk = dest->get_address(dest);
+	len = chunk.len * 8;
+	prefix = prefix < 0 ? len : min(prefix, len);
+	match_net = prefix != len;
+
+	memset(&request, 0, sizeof(request));
+
+	family = dest->get_family(dest);
+	hdr = &request.hdr;
+	hdr->nlmsg_flags = NLM_F_REQUEST;
+	hdr->nlmsg_type = RTM_GETROUTE;
+	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+
+	msg = NLMSG_DATA(hdr);
+	msg->rtm_family = family;
+	if (!match_net && this->rta_mark && this->routing_mark.value)
+	{
+		/* if our routing rule excludes packets with a certain mark we can
+		 * get the preferred route without having to dump all routes */
+		chunk = chunk_from_thing(this->routing_mark.value);
+		netlink_add_attribute(hdr, RTA_MARK, chunk, sizeof(request));
+	}
+	else if (family == AF_INET || this->rta_prefsrc_for_ipv6 ||
+			 this->routing_table || match_net)
+	{	/* kernels prior to 3.0 do not support RTA_PREFSRC for IPv6 routes.
+		 * as we want to ignore routes with virtual IPs we cannot use DUMP
+		 * if these routes are not installed in a separate table */
+		hdr->nlmsg_flags |= NLM_F_DUMP;
+	}
+	if (candidate)
+	{
+		chunk = candidate->get_address(candidate);
+		netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request));
+	}
+	/* we use this below to match against the routes */
+	chunk = dest->get_address(dest);
+	if (!match_net)
+	{
+		netlink_add_attribute(hdr, RTA_DST, chunk, sizeof(request));
+	}
+
+	if (this->socket->send(this->socket, hdr, &out, &len) != SUCCESS)
+	{
+		DBG2(DBG_KNL, "getting %s to reach %H/%d failed",
+			 nexthop ? "nexthop" : "address", dest, prefix);
+		return NULL;
+	}
+	routes = linked_list_create();
+	this->lock->read_lock(this->lock);
+
+	for (current = out; NLMSG_OK(current, len);
+		 current = NLMSG_NEXT(current, len))
+	{
+		switch (current->nlmsg_type)
+		{
+			case NLMSG_DONE:
+				break;
+			case RTM_NEWROUTE:
+			{
+				rt_entry_t *other;
+				uintptr_t table;
+
+				if (!route_usable(current))
+				{
+					continue;
+				}
+				route = parse_route(current, route);
+
+				table = (uintptr_t)route->table;
+				if (this->rt_exclude->find_first(this->rt_exclude, NULL,
+												 (void**)&table) == SUCCESS)
+				{	/* route is from an excluded routing table */
+					continue;
+				}
+				if (this->routing_table != 0 &&
+					route->table == this->routing_table)
+				{	/* route is from our own ipsec routing table */
+					continue;
+				}
+				if (route->oif && !is_interface_up_and_usable(this, route->oif))
+				{	/* interface is down */
+					continue;
+				}
+				if (!addr_in_subnet(chunk, prefix, route->dst, route->dst_len))
+				{	/* route destination does not contain dest */
+					continue;
+				}
+				if (route->src.ptr)
+				{	/* verify source address, if any */
+					host_t *src = host_create_from_chunk(msg->rtm_family,
+														 route->src, 0);
+					if (src && is_known_vip(this, src))
+					{	/* ignore routes installed by us */
+						src->destroy(src);
+						continue;
+					}
+					route->src_host = src;
+				}
+				/* insert route, sorted by priority and network prefix */
+				enumerator = routes->create_enumerator(routes);
+				while (enumerator->enumerate(enumerator, &other))
+				{
+					if (route->priority < other->priority)
+					{
+						break;
+					}
+					if (route->priority == other->priority &&
+						route->dst_len > other->dst_len)
+					{
+						break;
+					}
+				}
+				routes->insert_before(routes, enumerator, route);
+				enumerator->destroy(enumerator);
+				route = NULL;
+				continue;
+			}
+			default:
+				continue;
+		}
+		break;
+	}
+	if (route)
+	{
+		rt_entry_destroy(route);
+	}
+
+	/* now we have a list of routes matching dest, sorted by net prefix.
+	 * we will look for source addresses for these routes and select the one
+	 * with the preferred source address, if possible */
+	enumerator = routes->create_enumerator(routes);
+	while (enumerator->enumerate(enumerator, &route))
+	{
+		if (route->src_host)
+		{	/* got a source address with the route, if no preferred source
+			 * is given or it matches we are done, as this is the best route */
+			if (!candidate || candidate->ip_equals(candidate, route->src_host))
+			{
+				best = route;
+				break;
+			}
+			else if (route->oif)
+			{	/* no match yet, maybe it is assigned to the same interface */
+				host_t *src = get_interface_address(this, route->oif,
+											msg->rtm_family, dest, candidate);
+				if (src && src->ip_equals(src, candidate))
+				{
+					route->src_host->destroy(route->src_host);
+					route->src_host = src;
+					best = route;
+					break;
+				}
+				DESTROY_IF(src);
+			}
+			/* no luck yet with the source address. if this is the best (first)
+			 * route we store it as fallback in case we don't find a route with
+			 * the preferred source */
+			best = best ?: route;
+			continue;
+		}
+		if (route->oif)
+		{	/* no src, but an interface - get address from it */
+			route->src_host = get_interface_address(this, route->oif,
+											msg->rtm_family, dest, candidate);
+			if (route->src_host)
+			{	/* we handle this address the same as the one above */
+				if (!candidate ||
+					 candidate->ip_equals(candidate, route->src_host))
+				{
+					best = route;
+					break;
+				}
+				best = best ?: route;
+				continue;
+			}
+		}
+		if (route->gtw.ptr)
+		{	/* no src, no iface, but a gateway - lookup src to reach gtw */
+			host_t *gtw;
+
+			gtw = host_create_from_chunk(msg->rtm_family, route->gtw, 0);
+			if (gtw && !gtw->ip_equals(gtw, dest))
+			{
+				route->src_host = get_route(this, gtw, -1, FALSE, candidate,
+											recursion + 1);
+			}
+			DESTROY_IF(gtw);
+			if (route->src_host)
+			{	/* more of the same */
+				if (!candidate ||
+					 candidate->ip_equals(candidate, route->src_host))
+				{
+					best = route;
+					break;
+				}
+				best = best ?: route;
+			}
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	if (nexthop)
+	{	/* nexthop lookup, return gateway if any */
+		if (best || routes->get_first(routes, (void**)&best) == SUCCESS)
+		{
+			addr = host_create_from_chunk(msg->rtm_family, best->gtw, 0);
+		}
+		if (!addr && !match_net)
+		{	/* fallback to destination address */
+			addr = dest->clone(dest);
+		}
+	}
+	else
+	{
+		if (best)
+		{
+			addr = best->src_host->clone(best->src_host);
+		}
+	}
+	this->lock->unlock(this->lock);
+	routes->destroy_function(routes, (void*)rt_entry_destroy);
+	free(out);
+
+	if (addr)
+	{
+		DBG2(DBG_KNL, "using %H as %s to reach %H/%d", addr,
+			 nexthop ? "nexthop" : "address", dest, prefix);
+	}
+	else if (!recursion)
+	{
+		DBG2(DBG_KNL, "no %s found to reach %H/%d",
+			 nexthop ? "nexthop" : "address", dest, prefix);
+	}
+	return addr;
+}
+
+METHOD(kernel_net_t, get_source_addr, host_t*,
+	private_kernel_netlink_net_t *this, host_t *dest, host_t *src)
+{
+	return get_route(this, dest, -1, FALSE, src, 0);
+}
+
+METHOD(kernel_net_t, get_nexthop, host_t*,
+	private_kernel_netlink_net_t *this, host_t *dest, int prefix, host_t *src)
+{
+	return get_route(this, dest, prefix, TRUE, src, 0);
+}
+
+/**
+ * Manages the creation and deletion of ip addresses on an interface.
+ * By setting the appropriate nlmsg_type, the ip will be set or unset.
+ */
+static status_t manage_ipaddr(private_kernel_netlink_net_t *this, int nlmsg_type,
+							  int flags, int if_index, host_t *ip, int prefix)
+{
+	netlink_buf_t request;
+	struct nlmsghdr *hdr;
+	struct ifaddrmsg *msg;
+	chunk_t chunk;
+
+	memset(&request, 0, sizeof(request));
+
+	chunk = ip->get_address(ip);
+
+	hdr = &request.hdr;
+	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
+	hdr->nlmsg_type = nlmsg_type;
+	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
+
+	msg = NLMSG_DATA(hdr);
+	msg->ifa_family = ip->get_family(ip);
+	msg->ifa_flags = 0;
+	msg->ifa_prefixlen = prefix < 0 ? chunk.len * 8 : prefix;
+	msg->ifa_scope = RT_SCOPE_UNIVERSE;
+	msg->ifa_index = if_index;
+
+	netlink_add_attribute(hdr, IFA_LOCAL, chunk, sizeof(request));
+
+	if (ip->get_family(ip) == AF_INET6 && this->rta_prefsrc_for_ipv6)
+	{	/* if source routes are possible we let the virtual IP get deprecated
+		 * immediately (but mark it as valid forever) so it gets only used if
+		 * forced by our route, and not by the default IPv6 address selection */
+		struct ifa_cacheinfo cache = {
+			.ifa_valid = 0xFFFFFFFF,
+			.ifa_prefered = 0,
+		};
+		netlink_add_attribute(hdr, IFA_CACHEINFO, chunk_from_thing(cache),
+							  sizeof(request));
+	}
+	return this->socket->send_ack(this->socket, hdr);
+}
+
+METHOD(kernel_net_t, add_ip, status_t,
+	private_kernel_netlink_net_t *this, host_t *virtual_ip, int prefix,
+	char *iface_name)
+{
+	addr_map_entry_t *entry, lookup = {
+		.ip = virtual_ip,
+	};
+	iface_entry_t *iface = NULL;
+
+	if (!this->install_virtual_ip)
+	{	/* disabled by config */
+		return SUCCESS;
+	}
+
+	this->lock->write_lock(this->lock);
+	/* the virtual IP might actually be installed as regular IP, in which case
+	 * we don't track it as virtual IP */
+	entry = this->addrs->get_match(this->addrs, &lookup,
+								  (void*)addr_map_entry_match);
+	if (!entry)
+	{	/* otherwise it might already be installed as virtual IP */
+		entry = this->vips->get_match(this->vips, &lookup,
+									 (void*)addr_map_entry_match);
+		if (entry)
+		{	/* the vip we found can be in one of three states: 1) installed and
+			 * ready, 2) just added by another thread, but not yet confirmed to
+			 * be installed by the kernel, 3) just deleted, but not yet gone.
+			 * Then while we wait below, several things could happen (as we
+			 * release the lock).  For instance, the interface could disappear,
+			 * or the IP is finally deleted, and it reappears on a different
+			 * interface. All these cases are handled by the call below. */
+			while (!is_vip_installed_or_gone(this, virtual_ip, &entry))
+			{
+				this->condvar->wait(this->condvar, this->lock);
+			}
+			if (entry)
+			{
+				entry->addr->refcount++;
+			}
+		}
+	}
+	if (entry)
+	{
+		DBG2(DBG_KNL, "virtual IP %H is already installed on %s", virtual_ip,
+			 entry->iface->ifname);
+		this->lock->unlock(this->lock);
+		return SUCCESS;
+	}
+	/* try to find the target interface, either by config or via src ip */
+	if (!this->install_virtual_ip_on ||
+		 this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_name,
+						(void**)&iface, this->install_virtual_ip_on) != SUCCESS)
+	{
+		if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_name,
+									 (void**)&iface, iface_name) != SUCCESS)
+		{	/* if we don't find the requested interface we just use the first */
+			this->ifaces->get_first(this->ifaces, (void**)&iface);
+		}
+	}
+	if (iface)
+	{
+		addr_entry_t *addr;
+		char *ifname;
+		int ifi;
+
+		INIT(addr,
+			.ip = virtual_ip->clone(virtual_ip),
+			.refcount = 1,
+			.scope = RT_SCOPE_UNIVERSE,
+		);
+		iface->addrs->insert_last(iface->addrs, addr);
+		addr_map_entry_add(this->vips, addr, iface);
+		ifi = iface->ifindex;
+		this->lock->unlock(this->lock);
+		if (manage_ipaddr(this, RTM_NEWADDR, NLM_F_CREATE | NLM_F_EXCL,
+						  ifi, virtual_ip, prefix) == SUCCESS)
+		{
+			this->lock->write_lock(this->lock);
+			while (!is_vip_installed_or_gone(this, virtual_ip, &entry))
+			{	/* wait until address appears */
+				this->condvar->wait(this->condvar, this->lock);
+			}
+			if (entry)
+			{	/* we fail if the interface got deleted in the meantime */
+				ifname = strdup(entry->iface->ifname);
+				this->lock->unlock(this->lock);
+				DBG2(DBG_KNL, "virtual IP %H installed on %s",
+					 virtual_ip, ifname);
+				/* during IKEv1 reauthentication, children get moved from
+				 * old the new SA before the virtual IP is available. This
+				 * kills the route for our virtual IP, reinstall. */
+				queue_route_reinstall(this, ifname);
+				return SUCCESS;
+			}
+			this->lock->unlock(this->lock);
+		}
+		DBG1(DBG_KNL, "adding virtual IP %H failed", virtual_ip);
+		return FAILED;
+	}
+	this->lock->unlock(this->lock);
+	DBG1(DBG_KNL, "no interface available, unable to install virtual IP %H",
+		 virtual_ip);
+	return FAILED;
+}
+
+METHOD(kernel_net_t, del_ip, status_t,
+	private_kernel_netlink_net_t *this, host_t *virtual_ip, int prefix,
+	bool wait)
+{
+	addr_map_entry_t *entry, lookup = {
+		.ip = virtual_ip,
+	};
+
+	if (!this->install_virtual_ip)
+	{	/* disabled by config */
+		return SUCCESS;
+	}
+
+	DBG2(DBG_KNL, "deleting virtual IP %H", virtual_ip);
+
+	this->lock->write_lock(this->lock);
+	entry = this->vips->get_match(this->vips, &lookup,
+								 (void*)addr_map_entry_match);
+	if (!entry)
+	{	/* we didn't install this IP as virtual IP */
+		entry = this->addrs->get_match(this->addrs, &lookup,
+									  (void*)addr_map_entry_match);
+		if (entry)
+		{
+			DBG2(DBG_KNL, "not deleting existing IP %H on %s", virtual_ip,
+				 entry->iface->ifname);
+			this->lock->unlock(this->lock);
+			return SUCCESS;
+		}
+		DBG2(DBG_KNL, "virtual IP %H not cached, unable to delete", virtual_ip);
+		this->lock->unlock(this->lock);
+		return FAILED;
+	}
+	if (entry->addr->refcount == 1)
+	{
+		status_t status;
+		int ifi;
+
+		/* we set this flag so that threads calling add_ip will block and wait
+		 * until the entry is gone, also so we can wait below */
+		entry->addr->installed = FALSE;
+		ifi = entry->iface->ifindex;
+		this->lock->unlock(this->lock);
+		status = manage_ipaddr(this, RTM_DELADDR, 0, ifi, virtual_ip, prefix);
+		if (status == SUCCESS && wait)
+		{	/* wait until the address is really gone */
+			this->lock->write_lock(this->lock);
+			while (is_known_vip(this, virtual_ip))
+			{
+				this->condvar->wait(this->condvar, this->lock);
+			}
+			this->lock->unlock(this->lock);
+		}
+		return status;
+	}
+	else
+	{
+		entry->addr->refcount--;
+	}
+	DBG2(DBG_KNL, "virtual IP %H used by other SAs, not deleting",
+		 virtual_ip);
+	this->lock->unlock(this->lock);
+	return SUCCESS;
+}
+
+/**
+ * Manages source routes in the routing table.
+ * By setting the appropriate nlmsg_type, the route gets added or removed.
+ */
+static status_t manage_srcroute(private_kernel_netlink_net_t *this,
+								int nlmsg_type, int flags, chunk_t dst_net,
+								u_int8_t prefixlen, host_t *gateway,
+								host_t *src_ip, char *if_name)
+{
+	netlink_buf_t request;
+	struct nlmsghdr *hdr;
+	struct rtmsg *msg;
+	struct rtattr *rta;
+	int ifindex;
+	chunk_t chunk;
+
+	/* if route is 0.0.0.0/0, we can't install it, as it would
+	 * overwrite the default route. Instead, we add two routes:
+	 * 0.0.0.0/1 and 128.0.0.0/1 */
+	if (this->routing_table == 0 && prefixlen == 0)
+	{
+		chunk_t half_net;
+		u_int8_t half_prefixlen;
+		status_t status;
+
+		half_net = chunk_alloca(dst_net.len);
+		memset(half_net.ptr, 0, half_net.len);
+		half_prefixlen = 1;
+
+		status = manage_srcroute(this, nlmsg_type, flags, half_net, half_prefixlen,
+					gateway, src_ip, if_name);
+		half_net.ptr[0] |= 0x80;
+		status = manage_srcroute(this, nlmsg_type, flags, half_net, half_prefixlen,
+					gateway, src_ip, if_name);
+		return status;
+	}
+
+	memset(&request, 0, sizeof(request));
+
+	hdr = &request.hdr;
+	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
+	hdr->nlmsg_type = nlmsg_type;
+	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+
+	msg = NLMSG_DATA(hdr);
+	msg->rtm_family = src_ip->get_family(src_ip);
+	msg->rtm_dst_len = prefixlen;
+	msg->rtm_table = this->routing_table;
+	msg->rtm_protocol = RTPROT_STATIC;
+	msg->rtm_type = RTN_UNICAST;
+	msg->rtm_scope = RT_SCOPE_UNIVERSE;
+
+	netlink_add_attribute(hdr, RTA_DST, dst_net, sizeof(request));
+	chunk = src_ip->get_address(src_ip);
+	netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request));
+	if (gateway && gateway->get_family(gateway) == src_ip->get_family(src_ip))
+	{
+		chunk = gateway->get_address(gateway);
+		netlink_add_attribute(hdr, RTA_GATEWAY, chunk, sizeof(request));
+	}
+	ifindex = get_interface_index(this, if_name);
+	chunk.ptr = (char*)&ifindex;
+	chunk.len = sizeof(ifindex);
+	netlink_add_attribute(hdr, RTA_OIF, chunk, sizeof(request));
+
+	if (this->mtu || this->mss)
+	{
+		chunk = chunk_alloca(RTA_LENGTH((sizeof(struct rtattr) +
+										 sizeof(u_int32_t)) * 2));
+		chunk.len = 0;
+		rta = (struct rtattr*)chunk.ptr;
+		if (this->mtu)
+		{
+			rta->rta_type = RTAX_MTU;
+			rta->rta_len = RTA_LENGTH(sizeof(u_int32_t));
+			memcpy(RTA_DATA(rta), &this->mtu, sizeof(u_int32_t));
+			chunk.len = rta->rta_len;
+		}
+		if (this->mss)
+		{
+			rta = (struct rtattr*)(chunk.ptr + RTA_ALIGN(chunk.len));
+			rta->rta_type = RTAX_ADVMSS;
+			rta->rta_len = RTA_LENGTH(sizeof(u_int32_t));
+			memcpy(RTA_DATA(rta), &this->mss, sizeof(u_int32_t));
+			chunk.len = RTA_ALIGN(chunk.len) + rta->rta_len;
+		}
+		netlink_add_attribute(hdr, RTA_METRICS, chunk, sizeof(request));
+	}
+
+	return this->socket->send_ack(this->socket, hdr);
+}
+
+METHOD(kernel_net_t, add_route, status_t,
+	private_kernel_netlink_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
+	host_t *gateway, host_t *src_ip, char *if_name)
+{
+	status_t status;
+	route_entry_t *found, route = {
+		.dst_net = dst_net,
+		.prefixlen = prefixlen,
+		.gateway = gateway,
+		.src_ip = src_ip,
+		.if_name = if_name,
+	};
+
+	this->routes_lock->lock(this->routes_lock);
+	found = this->routes->get(this->routes, &route);
+	if (found)
+	{
+		this->routes_lock->unlock(this->routes_lock);
+		return ALREADY_DONE;
+	}
+	status = manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL,
+							 dst_net, prefixlen, gateway, src_ip, if_name);
+	if (status == SUCCESS)
+	{
+		found = route_entry_clone(&route);
+		this->routes->put(this->routes, found, found);
+	}
+	this->routes_lock->unlock(this->routes_lock);
+	return status;
+}
+
+METHOD(kernel_net_t, del_route, status_t,
+	private_kernel_netlink_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
+	host_t *gateway, host_t *src_ip, char *if_name)
+{
+	status_t status;
+	route_entry_t *found, route = {
+		.dst_net = dst_net,
+		.prefixlen = prefixlen,
+		.gateway = gateway,
+		.src_ip = src_ip,
+		.if_name = if_name,
+	};
+
+	this->routes_lock->lock(this->routes_lock);
+	found = this->routes->get(this->routes, &route);
+	if (!found)
+	{
+		this->routes_lock->unlock(this->routes_lock);
+		return NOT_FOUND;
+	}
+	this->routes->remove(this->routes, found);
+	route_entry_destroy(found);
+	status = manage_srcroute(this, RTM_DELROUTE, 0, dst_net, prefixlen,
+							 gateway, src_ip, if_name);
+	this->routes_lock->unlock(this->routes_lock);
+	return status;
+}
+
+/**
+ * Initialize a list of local addresses.
+ */
+static status_t init_address_list(private_kernel_netlink_net_t *this)
+{
+	netlink_buf_t request;
+	struct nlmsghdr *out, *current, *in;
+	struct rtgenmsg *msg;
+	size_t len;
+	enumerator_t *ifaces, *addrs;
+	iface_entry_t *iface;
+	addr_entry_t *addr;
+
+	DBG2(DBG_KNL, "known interfaces and IP addresses:");
+
+	memset(&request, 0, sizeof(request));
+
+	in = &request.hdr;
+	in->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
+	in->nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT;
+	msg = NLMSG_DATA(in);
+	msg->rtgen_family = AF_UNSPEC;
+
+	/* get all links */
+	in->nlmsg_type = RTM_GETLINK;
+	if (this->socket->send(this->socket, in, &out, &len) != SUCCESS)
+	{
+		return FAILED;
+	}
+	current = out;
+	while (NLMSG_OK(current, len))
+	{
+		switch (current->nlmsg_type)
+		{
+			case NLMSG_DONE:
+				break;
+			case RTM_NEWLINK:
+				process_link(this, current, FALSE);
+				/* fall through */
+			default:
+				current = NLMSG_NEXT(current, len);
+				continue;
+		}
+		break;
+	}
+	free(out);
+
+	/* get all interface addresses */
+	in->nlmsg_type = RTM_GETADDR;
+	if (this->socket->send(this->socket, in, &out, &len) != SUCCESS)
+	{
+		return FAILED;
+	}
+	current = out;
+	while (NLMSG_OK(current, len))
+	{
+		switch (current->nlmsg_type)
+		{
+			case NLMSG_DONE:
+				break;
+			case RTM_NEWADDR:
+				process_addr(this, current, FALSE);
+				/* fall through */
+			default:
+				current = NLMSG_NEXT(current, len);
+				continue;
+		}
+		break;
+	}
+	free(out);
+
+	this->lock->read_lock(this->lock);
+	ifaces = this->ifaces->create_enumerator(this->ifaces);
+	while (ifaces->enumerate(ifaces, &iface))
+	{
+		if (iface_entry_up_and_usable(iface))
+		{
+			DBG2(DBG_KNL, "  %s", iface->ifname);
+			addrs = iface->addrs->create_enumerator(iface->addrs);
+			while (addrs->enumerate(addrs, (void**)&addr))
+			{
+				DBG2(DBG_KNL, "    %H", addr->ip);
+			}
+			addrs->destroy(addrs);
+		}
+	}
+	ifaces->destroy(ifaces);
+	this->lock->unlock(this->lock);
+	return SUCCESS;
+}
+
+/**
+ * create or delete a rule to use our routing table
+ */
+static status_t manage_rule(private_kernel_netlink_net_t *this, int nlmsg_type,
+							int family, u_int32_t table, u_int32_t prio)
+{
+	netlink_buf_t request;
+	struct nlmsghdr *hdr;
+	struct rtmsg *msg;
+	chunk_t chunk;
+	char *fwmark;
+
+	memset(&request, 0, sizeof(request));
+	hdr = &request.hdr;
+	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+	hdr->nlmsg_type = nlmsg_type;
+	if (nlmsg_type == RTM_NEWRULE)
+	{
+		hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
+	}
+	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+
+	msg = NLMSG_DATA(hdr);
+	msg->rtm_table = table;
+	msg->rtm_family = family;
+	msg->rtm_protocol = RTPROT_BOOT;
+	msg->rtm_scope = RT_SCOPE_UNIVERSE;
+	msg->rtm_type = RTN_UNICAST;
+
+	chunk = chunk_from_thing(prio);
+	netlink_add_attribute(hdr, RTA_PRIORITY, chunk, sizeof(request));
+
+	fwmark = lib->settings->get_str(lib->settings,
+							"%s.plugins.kernel-netlink.fwmark", NULL, lib->ns);
+	if (fwmark)
+	{
+#ifdef HAVE_LINUX_FIB_RULES_H
+		mark_t mark;
+
+		if (fwmark[0] == '!')
+		{
+			msg->rtm_flags |= FIB_RULE_INVERT;
+			fwmark++;
+		}
+		if (mark_from_string(fwmark, &mark))
+		{
+			chunk = chunk_from_thing(mark.value);
+			netlink_add_attribute(hdr, FRA_FWMARK, chunk, sizeof(request));
+			chunk = chunk_from_thing(mark.mask);
+			netlink_add_attribute(hdr, FRA_FWMASK, chunk, sizeof(request));
+			if (msg->rtm_flags & FIB_RULE_INVERT)
+			{
+				this->routing_mark = mark;
+			}
+		}
+#else
+		DBG1(DBG_KNL, "setting firewall mark on routing rule is not supported");
+#endif
+	}
+	return this->socket->send_ack(this->socket, hdr);
+}
+
+/**
+ * check for kernel features (currently only via version number)
+ */
+static void check_kernel_features(private_kernel_netlink_net_t *this)
+{
+	struct utsname utsname;
+	int a, b, c;
+
+	if (uname(&utsname) == 0)
+	{
+		switch(sscanf(utsname.release, "%d.%d.%d", &a, &b, &c))
+		{
+			case 3:
+				if (a == 2)
+				{
+					if (b == 6 && c >= 36)
+					{
+						this->rta_mark = TRUE;
+					}
+					DBG2(DBG_KNL, "detected Linux %d.%d.%d, no support for "
+						 "RTA_PREFSRC for IPv6 routes", a, b, c);
+					break;
+				}
+				/* fall-through */
+			case 2:
+				/* only 3.x+ uses two part version numbers */
+				this->rta_prefsrc_for_ipv6 = TRUE;
+				this->rta_mark = TRUE;
+				break;
+			default:
+				break;
+		}
+	}
+}
+
+/**
+ * Destroy an address to iface map
+ */
+static void addr_map_destroy(hashtable_t *map)
+{
+	enumerator_t *enumerator;
+	addr_map_entry_t *addr;
+
+	enumerator = map->create_enumerator(map);
+	while (enumerator->enumerate(enumerator, NULL, (void**)&addr))
+	{
+		free(addr);
+	}
+	enumerator->destroy(enumerator);
+	map->destroy(map);
+}
+
+METHOD(kernel_net_t, destroy, void,
+	private_kernel_netlink_net_t *this)
+{
+	enumerator_t *enumerator;
+	route_entry_t *route;
+
+	if (this->routing_table)
+	{
+		manage_rule(this, RTM_DELRULE, AF_INET, this->routing_table,
+					this->routing_table_prio);
+		manage_rule(this, RTM_DELRULE, AF_INET6, this->routing_table,
+					this->routing_table_prio);
+	}
+	if (this->socket_events > 0)
+	{
+		lib->watcher->remove(lib->watcher, this->socket_events);
+		close(this->socket_events);
+	}
+	enumerator = this->routes->create_enumerator(this->routes);
+	while (enumerator->enumerate(enumerator, NULL, (void**)&route))
+	{
+		manage_srcroute(this, RTM_DELROUTE, 0, route->dst_net, route->prefixlen,
+						route->gateway, route->src_ip, route->if_name);
+		route_entry_destroy(route);
+	}
+	enumerator->destroy(enumerator);
+	this->routes->destroy(this->routes);
+	this->routes_lock->destroy(this->routes_lock);
+	DESTROY_IF(this->socket);
+
+	net_changes_clear(this);
+	this->net_changes->destroy(this->net_changes);
+	this->net_changes_lock->destroy(this->net_changes_lock);
+
+	addr_map_destroy(this->addrs);
+	addr_map_destroy(this->vips);
+
+	this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
+	this->rt_exclude->destroy(this->rt_exclude);
+	this->roam_lock->destroy(this->roam_lock);
+	this->condvar->destroy(this->condvar);
+	this->lock->destroy(this->lock);
+	free(this);
+}
+
+/*
+ * Described in header.
+ */
+kernel_netlink_net_t *kernel_netlink_net_create()
+{
+	private_kernel_netlink_net_t *this;
+	enumerator_t *enumerator;
+	bool register_for_events = TRUE;
+	char *exclude;
+
+	INIT(this,
+		.public = {
+			.interface = {
+				.get_interface = _get_interface_name,
+				.create_address_enumerator = _create_address_enumerator,
+				.get_source_addr = _get_source_addr,
+				.get_nexthop = _get_nexthop,
+				.add_ip = _add_ip,
+				.del_ip = _del_ip,
+				.add_route = _add_route,
+				.del_route = _del_route,
+				.destroy = _destroy,
+			},
+		},
+		.socket = netlink_socket_create(NETLINK_ROUTE, rt_msg_names,
+			lib->settings->get_bool(lib->settings,
+				"%s.plugins.kernel-netlink.parallel_route", FALSE, lib->ns)),
+		.rt_exclude = linked_list_create(),
+		.routes = hashtable_create((hashtable_hash_t)route_entry_hash,
+								   (hashtable_equals_t)route_entry_equals, 16),
+		.net_changes = hashtable_create(
+								   (hashtable_hash_t)net_change_hash,
+								   (hashtable_equals_t)net_change_equals, 16),
+		.addrs = hashtable_create(
+								(hashtable_hash_t)addr_map_entry_hash,
+								(hashtable_equals_t)addr_map_entry_equals, 16),
+		.vips = hashtable_create((hashtable_hash_t)addr_map_entry_hash,
+								 (hashtable_equals_t)addr_map_entry_equals, 16),
+		.routes_lock = mutex_create(MUTEX_TYPE_DEFAULT),
+		.net_changes_lock = mutex_create(MUTEX_TYPE_DEFAULT),
+		.ifaces = linked_list_create(),
+		.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+		.condvar = rwlock_condvar_create(),
+		.roam_lock = spinlock_create(),
+		.routing_table = lib->settings->get_int(lib->settings,
+						"%s.routing_table", ROUTING_TABLE, lib->ns),
+		.routing_table_prio = lib->settings->get_int(lib->settings,
+						"%s.routing_table_prio", ROUTING_TABLE_PRIO, lib->ns),
+		.process_route = lib->settings->get_bool(lib->settings,
+						"%s.process_route", TRUE, lib->ns),
+		.install_virtual_ip = lib->settings->get_bool(lib->settings,
+						"%s.install_virtual_ip", TRUE, lib->ns),
+		.install_virtual_ip_on = lib->settings->get_str(lib->settings,
+						"%s.install_virtual_ip_on", NULL, lib->ns),
+		.prefer_temporary_addrs = lib->settings->get_bool(lib->settings,
+						"%s.prefer_temporary_addrs", FALSE, lib->ns),
+		.roam_events = lib->settings->get_bool(lib->settings,
+						"%s.plugins.kernel-netlink.roam_events", TRUE, lib->ns),
+		.mtu = lib->settings->get_int(lib->settings,
+						"%s.plugins.kernel-netlink.mtu", 0, lib->ns),
+		.mss = lib->settings->get_int(lib->settings,
+						"%s.plugins.kernel-netlink.mss", 0, lib->ns),
+	);
+	timerclear(&this->last_route_reinstall);
+	timerclear(&this->next_roam);
+
+	check_kernel_features(this);
+
+	if (streq(lib->ns, "starter"))
+	{	/* starter has no threads, so we do not register for kernel events */
+		register_for_events = FALSE;
+	}
+
+	exclude = lib->settings->get_str(lib->settings,
+									 "%s.ignore_routing_tables", NULL, lib->ns);
+	if (exclude)
+	{
+		char *token;
+		uintptr_t table;
+
+		enumerator = enumerator_create_token(exclude, " ", " ");
+		while (enumerator->enumerate(enumerator, &token))
+		{
+			errno = 0;
+			table = strtoul(token, NULL, 10);
+
+			if (errno == 0)
+			{
+				this->rt_exclude->insert_last(this->rt_exclude, (void*)table);
+			}
+		}
+		enumerator->destroy(enumerator);
+	}
+
+	if (register_for_events)
+	{
+		struct sockaddr_nl addr;
+
+		memset(&addr, 0, sizeof(addr));
+		addr.nl_family = AF_NETLINK;
+
+		/* create and bind RT socket for events (address/interface/route changes) */
+		this->socket_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+		if (this->socket_events < 0)
+		{
+			DBG1(DBG_KNL, "unable to create RT event socket");
+			destroy(this);
+			return NULL;
+		}
+		addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |
+						 RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_LINK;
+		if (bind(this->socket_events, (struct sockaddr*)&addr, sizeof(addr)))
+		{
+			DBG1(DBG_KNL, "unable to bind RT event socket");
+			destroy(this);
+			return NULL;
+		}
+
+		lib->watcher->add(lib->watcher, this->socket_events, WATCHER_READ,
+						  (watcher_cb_t)receive_events, this);
+	}
+
+	if (init_address_list(this) != SUCCESS)
+	{
+		DBG1(DBG_KNL, "unable to get interface list");
+		destroy(this);
+		return NULL;
+	}
+
+	if (this->routing_table)
+	{
+		if (manage_rule(this, RTM_NEWRULE, AF_INET, this->routing_table,
+						this->routing_table_prio) != SUCCESS)
+		{
+			DBG1(DBG_KNL, "unable to create IPv4 routing table rule");
+		}
+		if (manage_rule(this, RTM_NEWRULE, AF_INET6, this->routing_table,
+						this->routing_table_prio) != SUCCESS)
+		{
+			DBG1(DBG_KNL, "unable to create IPv6 routing table rule");
+		}
+	}
+
+	return &this->public;
+}
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.h b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.h
similarity index 100%
rename from src/libhydra/plugins/kernel_netlink/kernel_netlink_net.h
rename to src/libcharon/plugins/kernel_netlink/kernel_netlink_net.h
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c
new file mode 100644
index 0000000..8bafc3c
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.c
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+
+#include "kernel_netlink_plugin.h"
+
+#include "kernel_netlink_ipsec.h"
+#include "kernel_netlink_net.h"
+
+typedef struct private_kernel_netlink_plugin_t private_kernel_netlink_plugin_t;
+
+/**
+ * private data of kernel netlink plugin
+ */
+struct private_kernel_netlink_plugin_t {
+	/**
+	 * implements plugin interface
+	 */
+	kernel_netlink_plugin_t public;
+};
+
+METHOD(plugin_t, get_name, char*,
+	private_kernel_netlink_plugin_t *this)
+{
+	return "kernel-netlink";
+}
+
+METHOD(plugin_t, get_features, int,
+	private_kernel_netlink_plugin_t *this, plugin_feature_t *features[])
+{
+	static plugin_feature_t f[] = {
+		PLUGIN_CALLBACK(kernel_ipsec_register, kernel_netlink_ipsec_create),
+			PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"),
+		PLUGIN_CALLBACK(kernel_net_register, kernel_netlink_net_create),
+			PLUGIN_PROVIDE(CUSTOM, "kernel-net"),
+	};
+	*features = f;
+	return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+	private_kernel_netlink_plugin_t *this)
+{
+	free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *kernel_netlink_plugin_create()
+{
+	private_kernel_netlink_plugin_t *this;
+
+	if (!lib->caps->keep(lib->caps, CAP_NET_ADMIN))
+	{	/* required to bind/use XFRM sockets / create/modify routing tables, but
+		 * not if only the read-only parts of kernel-netlink-net are used, so
+		 * we don't fail here */
+		DBG1(DBG_KNL, "kernel-netlink plugin might require CAP_NET_ADMIN "
+			 "capability");
+	}
+
+	INIT(this,
+		.public = {
+			.plugin = {
+				.get_name = _get_name,
+				.get_features = _get_features,
+				.destroy = _destroy,
+			},
+		},
+	);
+
+	return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.h b/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.h
new file mode 100644
index 0000000..74c9ae2
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup kernel_netlink kernel_netlink
+ * @ingroup cplugins
+ *
+ * @defgroup kernel_netlink_plugin kernel_netlink_plugin
+ * @{ @ingroup kernel_netlink
+ */
+
+#ifndef KERNEL_NETLINK_PLUGIN_H_
+#define KERNEL_NETLINK_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct kernel_netlink_plugin_t kernel_netlink_plugin_t;
+
+/**
+ * netlink kernel interface plugin
+ */
+struct kernel_netlink_plugin_t {
+
+	/**
+	 * implements plugin interface
+	 */
+	plugin_t plugin;
+};
+
+#endif /** KERNEL_NETLINK_PLUGIN_H_ @}*/
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c
similarity index 100%
rename from src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c
rename to src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h
new file mode 100644
index 0000000..b034326
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+#ifndef KERNEL_NETLINK_SHARED_H_
+#define KERNEL_NETLINK_SHARED_H_
+
+#include <library.h>
+
+#include <linux/rtnetlink.h>
+
+/**
+ * Default buffer size.
+ *
+ * 1024 byte is currently sufficient for all operations.
+ */
+#ifndef KERNEL_NETLINK_BUFSIZE
+#define KERNEL_NETLINK_BUFSIZE 1024
+#endif
+
+/**
+ * General purpose netlink buffer.
+ *
+ * Some platforms require an enforced aligment to four bytes (e.g. ARM).
+ */
+typedef union {
+	struct nlmsghdr hdr;
+	u_char bytes[KERNEL_NETLINK_BUFSIZE];
+} netlink_buf_t __attribute__((aligned(RTA_ALIGNTO)));
+
+typedef struct netlink_socket_t netlink_socket_t;
+
+/**
+ * Wrapper around a netlink socket.
+ */
+struct netlink_socket_t {
+
+	/**
+	 * Send a netlink message and wait for a reply.
+	 *
+	 * @param	in		netlink message to send
+	 * @param	out 	received netlink message
+	 * @param	out_len	length of the received message
+	 */
+	status_t (*send)(netlink_socket_t *this, struct nlmsghdr *in,
+					 struct nlmsghdr **out, size_t *out_len);
+
+	/**
+	 * Send a netlink message and wait for its acknowledge.
+	 *
+	 * @param	in		netlink message to send
+	 */
+	status_t (*send_ack)(netlink_socket_t *this, struct nlmsghdr *in);
+
+	/**
+	 * Destroy the socket.
+	 */
+	void (*destroy)(netlink_socket_t *this);
+};
+
+/**
+ * Create a netlink_socket_t object.
+ *
+ * @param protocol	protocol type (e.g. NETLINK_XFRM or NETLINK_ROUTE)
+ * @param names		optional enum names for Netlink messages
+ * @param parallel	support parallel queries on this Netlink socket
+ */
+netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names,
+										bool parallel);
+
+/**
+ * Creates an rtattr and adds it to the given netlink message.
+ *
+ * @param hdr			netlink message
+ * @param rta_type		type of the rtattr
+ * @param data			data to add to the rtattr
+ * @param buflen		length of the netlink message buffer
+ */
+void netlink_add_attribute(struct nlmsghdr *hdr, int rta_type, chunk_t data,
+						   size_t buflen);
+
+/**
+ * Reserve space in a netlink message for given size and type, returning buffer.
+ *
+ * @param hdr			netlink message
+ * @param buflen		size of full netlink buffer
+ * @param type			RTA type
+ * @param len			length of RTA data
+ * @return				buffer to len bytes of attribute data, NULL on error
+ */
+void* netlink_reserve(struct nlmsghdr *hdr, int buflen, int type, int len);
+
+#endif /* KERNEL_NETLINK_SHARED_H_ */
diff --git a/src/libhydra/plugins/kernel_netlink/suites/test_socket.c b/src/libcharon/plugins/kernel_netlink/suites/test_socket.c
similarity index 100%
rename from src/libhydra/plugins/kernel_netlink/suites/test_socket.c
rename to src/libcharon/plugins/kernel_netlink/suites/test_socket.c
diff --git a/src/libcharon/plugins/kernel_netlink/tests.c b/src/libcharon/plugins/kernel_netlink/tests.c
new file mode 100644
index 0000000..a1799ea
--- /dev/null
+++ b/src/libcharon/plugins/kernel_netlink/tests.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * 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.
+ */
+
+#include <test_runner.h>
+
+/* declare test suite constructors */
+#define TEST_SUITE(x) test_suite_t* x();
+#include "tests.h"
+#undef TEST_SUITE
+
+static test_configuration_t tests[] = {
+#define TEST_SUITE(x) \
+	{ .suite = x, },
+#include "tests.h"
+	{ .suite = NULL, }
+};
+
+static bool test_runner_init(bool init)
+{
+	if (init)
+	{
+		lib->processor->set_threads(lib->processor, 8);
+	}
+	else
+	{
+		lib->processor->set_threads(lib->processor, 0);
+		lib->processor->cancel(lib->processor);
+	}
+	return TRUE;
+}
+
+int main(int argc, char *argv[])
+{
+	return test_runner_run("kernel-netlink", tests, test_runner_init);
+}
diff --git a/src/libhydra/plugins/kernel_netlink/tests.h b/src/libcharon/plugins/kernel_netlink/tests.h
similarity index 100%
rename from src/libhydra/plugins/kernel_netlink/tests.h
rename to src/libcharon/plugins/kernel_netlink/tests.h
diff --git a/src/libcharon/plugins/kernel_pfkey/Makefile.am b/src/libcharon/plugins/kernel_pfkey/Makefile.am
new file mode 100644
index 0000000..8fdca93
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfkey/Makefile.am
@@ -0,0 +1,19 @@
+AM_CPPFLAGS = \
+	-I${linux_headers} \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+	$(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-kernel-pfkey.la
+else
+plugin_LTLIBRARIES = libstrongswan-kernel-pfkey.la
+endif
+
+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 -avoid-version
diff --git a/src/libcharon/plugins/kernel_pfkey/Makefile.in b/src/libcharon/plugins/kernel_pfkey/Makefile.in
new file mode 100644
index 0000000..f2876a2
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfkey/Makefile.in
@@ -0,0 +1,782 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 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.
+
+ at SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@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/libcharon/plugins/kernel_pfkey
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+	$(top_srcdir)/m4/config/ltoptions.m4 \
+	$(top_srcdir)/m4/config/ltsugar.m4 \
+	$(top_srcdir)/m4/config/ltversion.m4 \
+	$(top_srcdir)/m4/config/lt~obsolete.m4 \
+	$(top_srcdir)/m4/macros/split-package-version.m4 \
+	$(top_srcdir)/m4/macros/with.m4 \
+	$(top_srcdir)/m4/macros/enable-disable.m4 \
+	$(top_srcdir)/m4/macros/add-plugin.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_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 = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_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)
+AM_V_lt = $(am__v_lt_ at AM_V@)
+am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+libstrongswan_kernel_pfkey_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) \
+	$(libstrongswan_kernel_pfkey_la_LDFLAGS) $(LDFLAGS) -o $@
+ at MONOLITHIC_FALSE@am_libstrongswan_kernel_pfkey_la_rpath = -rpath \
+ at MONOLITHIC_FALSE@	$(plugindir)
+ at MONOLITHIC_TRUE@am_libstrongswan_kernel_pfkey_la_rpath =
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_ at AM_V@)
+am__v_CC_ = $(am__v_CC_ at AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_ at AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_ at AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(libstrongswan_kernel_pfkey_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_kernel_pfkey_la_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GEM = @GEM@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
+PTHREADLIB = @PTHREADLIB@
+PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+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_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+	-I${linux_headers} \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+	$(PLUGIN_CFLAGS)
+
+ at MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-kernel-pfkey.la
+ at MONOLITHIC_FALSE@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 -avoid-version
+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 ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_pfkey/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/libcharon/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
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+	}
+
+uninstall-pluginLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+	done
+
+clean-pluginLTLIBRARIES:
+	-test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+	@list='$(plugin_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+
+libstrongswan-kernel-pfkey.la: $(libstrongswan_kernel_pfkey_la_OBJECTS) $(libstrongswan_kernel_pfkey_la_DEPENDENCIES) $(EXTRA_libstrongswan_kernel_pfkey_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(libstrongswan_kernel_pfkey_la_LINK) $(am_libstrongswan_kernel_pfkey_la_rpath) $(libstrongswan_kernel_pfkey_la_OBJECTS) $(libstrongswan_kernel_pfkey_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_pfkey_ipsec.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_pfkey_plugin.Plo at am__quote@
+
+.c.o:
+ at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+ at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+ at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+ at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+ at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+ at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+ at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+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 "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$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:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-noinstLTLIBRARIES \
+	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
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+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 TAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+	cscopelist-am ctags ctags-am 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 tags-am 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/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
new file mode 100644
index 0000000..d505f1c
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
@@ -0,0 +1,3094 @@
+/*
+ * Copyright (C) 2008-2015 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.
+ */
+/*
+ * Copyright (C) 2014 Nanoteq Pty Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#ifdef __FreeBSD__
+#include <limits.h> /* for LONG_MAX */
+#endif
+
+#ifdef HAVE_NET_PFKEYV2_H
+#include <net/pfkeyv2.h>
+#else
+#include <linux/pfkeyv2.h>
+#endif
+
+#ifdef SADB_X_EXT_NAT_T_TYPE
+#define HAVE_NATT
+#endif
+
+#ifdef HAVE_NETIPSEC_IPSEC_H
+#include <netipsec/ipsec.h>
+#elif defined(HAVE_NETINET6_IPSEC_H)
+#include <netinet6/ipsec.h>
+#else
+#include <linux/ipsec.h>
+#endif
+
+#ifdef HAVE_NATT
+#ifdef HAVE_LINUX_UDP_H
+#include <linux/udp.h>
+#else
+#include <netinet/udp.h>
+#endif /*HAVE_LINUX_UDP_H*/
+#endif /*HAVE_NATT*/
+
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+#ifdef __APPLE__
+#include <sys/sysctl.h>
+#endif
+
+#include "kernel_pfkey_ipsec.h"
+
+#include <daemon.h>
+#include <utils/debug.h>
+#include <networking/host.h>
+#include <collections/linked_list.h>
+#include <collections/hashtable.h>
+#include <threading/mutex.h>
+
+/** non linux specific */
+#ifndef IPPROTO_COMP
+#ifdef IPPROTO_IPCOMP
+#define IPPROTO_COMP IPPROTO_IPCOMP
+#endif
+#endif
+
+#ifndef SADB_X_AALG_SHA2_256HMAC
+#define SADB_X_AALG_SHA2_256HMAC SADB_X_AALG_SHA2_256
+#define SADB_X_AALG_SHA2_384HMAC SADB_X_AALG_SHA2_384
+#define SADB_X_AALG_SHA2_512HMAC SADB_X_AALG_SHA2_512
+#endif
+
+#ifndef SADB_X_EALG_AESCBC
+#define SADB_X_EALG_AESCBC SADB_X_EALG_AES
+#endif
+
+#ifndef SADB_X_EALG_CASTCBC
+#define SADB_X_EALG_CASTCBC SADB_X_EALG_CAST128CBC
+#endif
+
+#if !defined(SADB_X_EALG_AES_GCM_ICV8) && defined(SADB_X_EALG_AESGCM8)
+#define SADB_X_EALG_AES_GCM_ICV8 SADB_X_EALG_AESGCM8
+#define SADB_X_EALG_AES_GCM_ICV12 SADB_X_EALG_AESGCM12
+#define SADB_X_EALG_AES_GCM_ICV16 SADB_X_EALG_AESGCM16
+#endif
+
+#ifndef SOL_IP
+#define SOL_IP IPPROTO_IP
+#define SOL_IPV6 IPPROTO_IPV6
+#endif
+
+/** from linux/in.h */
+#ifndef IP_IPSEC_POLICY
+#define IP_IPSEC_POLICY 16
+#endif
+
+/** missing on uclibc */
+#ifndef IPV6_IPSEC_POLICY
+#define IPV6_IPSEC_POLICY 34
+#endif
+
+/* from linux/udp.h */
+#ifndef UDP_ENCAP
+#define UDP_ENCAP 100
+#endif
+
+#ifndef UDP_ENCAP_ESPINUDP
+#define UDP_ENCAP_ESPINUDP 2
+#endif
+
+/* this is not defined on some platforms */
+#ifndef SOL_UDP
+#define SOL_UDP IPPROTO_UDP
+#endif
+
+/** base priority for installed policies */
+#define PRIO_BASE 384
+
+#ifdef __APPLE__
+/** from xnu/bsd/net/pfkeyv2.h */
+#define SADB_X_EXT_NATT 0x002
+	struct sadb_sa_2 {
+		struct sadb_sa	sa;
+		u_int16_t		sadb_sa_natt_port;
+		u_int16_t		sadb_reserved0;
+		u_int32_t		sadb_reserved1;
+	};
+#endif
+
+/** 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;
+
+	/**
+	 * List of exclude routes (exclude_route_t)
+	 */
+	linked_list_t *excludes;
+
+	/**
+	 * Hash table of IPsec SAs using policies (ipsec_sa_t)
+	 */
+	hashtable_t *sas;
+
+	/**
+	 * whether to install routes along policies
+	 */
+	bool install_routes;
+
+	/**
+	 * 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 exclude_route_t exclude_route_t;
+
+/**
+ * Exclude route definition
+ */
+struct exclude_route_t {
+	/** destination address of exclude */
+	host_t *dst;
+	/** source address for route */
+	host_t *src;
+	/** nexthop exclude has been installed */
+	host_t *gtw;
+	/** references to this route */
+	int refs;
+};
+
+/**
+ * clean up a route exclude entry
+ */
+static void exclude_route_destroy(exclude_route_t *this)
+{
+	this->dst->destroy(this->dst);
+	this->src->destroy(this->src);
+	this->gtw->destroy(this->gtw);
+	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;
+
+	/** reference to exclude route, if any */
+	exclude_route_t *exclude;
+};
+
+/**
+ * destroy an route_entry_t object
+ */
+static void route_entry_destroy(route_entry_t *this)
+{
+	free(this->if_name);
+	DESTROY_IF(this->src_ip);
+	DESTROY_IF(this->gateway);
+	chunk_free(&this->dst_net);
+	free(this);
+}
+
+/**
+ * compare two route_entry_t objects
+ */
+static bool route_entry_equals(route_entry_t *a, route_entry_t *b)
+{
+	return a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
+		   a->src_ip->ip_equals(a->src_ip, b->src_ip) &&
+		   a->gateway && b->gateway &&
+		   a->gateway->ip_equals(a->gateway, b->gateway) &&
+		   chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen;
+}
+
+typedef struct ipsec_sa_t ipsec_sa_t;
+
+/**
+ * IPsec SA assigned to a policy.
+ */
+struct ipsec_sa_t {
+	/** Source address of this SA */
+	host_t *src;
+
+	/** Destination address of this SA */
+	host_t *dst;
+
+	/** Description of this SA */
+	ipsec_sa_cfg_t cfg;
+
+	/** Reference count for this SA */
+	refcount_t refcount;
+};
+
+/**
+ * Hash function for ipsec_sa_t objects
+ */
+static u_int ipsec_sa_hash(ipsec_sa_t *sa)
+{
+	return chunk_hash_inc(sa->src->get_address(sa->src),
+						  chunk_hash_inc(sa->dst->get_address(sa->dst),
+						  chunk_hash(chunk_from_thing(sa->cfg))));
+}
+
+/**
+ * Equality function for ipsec_sa_t objects
+ */
+static bool ipsec_sa_equals(ipsec_sa_t *sa, ipsec_sa_t *other_sa)
+{
+	return sa->src->ip_equals(sa->src, other_sa->src) &&
+		   sa->dst->ip_equals(sa->dst, other_sa->dst) &&
+		   memeq(&sa->cfg, &other_sa->cfg, sizeof(ipsec_sa_cfg_t));
+}
+
+/**
+ * Allocate or reference an IPsec SA object
+ */
+static ipsec_sa_t *ipsec_sa_create(private_kernel_pfkey_ipsec_t *this,
+								   host_t *src, host_t *dst,
+								   ipsec_sa_cfg_t *cfg)
+{
+	ipsec_sa_t *sa, *found;
+	INIT(sa,
+		.src = src,
+		.dst = dst,
+		.cfg = *cfg,
+	);
+	found = this->sas->get(this->sas, sa);
+	if (!found)
+	{
+		sa->src = src->clone(src);
+		sa->dst = dst->clone(dst);
+		this->sas->put(this->sas, sa, sa);
+	}
+	else
+	{
+		free(sa);
+		sa = found;
+	}
+	ref_get(&sa->refcount);
+	return sa;
+}
+
+/**
+ * Release and destroy an IPsec SA object
+ */
+static void ipsec_sa_destroy(private_kernel_pfkey_ipsec_t *this,
+							 ipsec_sa_t *sa)
+{
+	if (ref_put(&sa->refcount))
+	{
+		this->sas->remove(this->sas, sa);
+		DESTROY_IF(sa->src);
+		DESTROY_IF(sa->dst);
+		free(sa);
+	}
+}
+
+typedef struct policy_sa_t policy_sa_t;
+typedef struct policy_sa_in_t policy_sa_in_t;
+
+/**
+ * Mapping between a policy and an IPsec SA.
+ */
+struct policy_sa_t {
+	/** Priority assigned to the policy when installed with this SA */
+	u_int32_t priority;
+
+	/** Type of the policy */
+	policy_type_t type;
+
+	/** Assigned SA */
+	ipsec_sa_t *sa;
+};
+
+/**
+ * For input policies we also cache the traffic selectors in order to install
+ * the route.
+ */
+struct policy_sa_in_t {
+	/** Generic interface */
+	policy_sa_t generic;
+
+	/** Source traffic selector of this policy */
+	traffic_selector_t *src_ts;
+
+	/** Destination traffic selector of this policy */
+	traffic_selector_t *dst_ts;
+};
+
+/**
+ * Create a policy_sa(_in)_t object
+ */
+static policy_sa_t *policy_sa_create(private_kernel_pfkey_ipsec_t *this,
+	policy_dir_t dir, policy_type_t type, host_t *src, host_t *dst,
+	traffic_selector_t *src_ts, traffic_selector_t *dst_ts, ipsec_sa_cfg_t *cfg)
+{
+	policy_sa_t *policy;
+
+	if (dir == POLICY_IN)
+	{
+		policy_sa_in_t *in;
+		INIT(in,
+			.src_ts = src_ts->clone(src_ts),
+			.dst_ts = dst_ts->clone(dst_ts),
+		);
+		policy = &in->generic;
+	}
+	else
+	{
+		INIT(policy, .priority = 0);
+	}
+	policy->type = type;
+	policy->sa = ipsec_sa_create(this, src, dst, cfg);
+	return policy;
+}
+
+/**
+ * Destroy a policy_sa(_in)_t object
+ */
+static void policy_sa_destroy(policy_sa_t *policy, policy_dir_t *dir,
+							  private_kernel_pfkey_ipsec_t *this)
+{
+	if (*dir == POLICY_IN)
+	{
+		policy_sa_in_t *in = (policy_sa_in_t*)policy;
+		in->src_ts->destroy(in->src_ts);
+		in->dst_ts->destroy(in->dst_ts);
+	}
+	ipsec_sa_destroy(this, policy->sa);
+	free(policy);
+}
+
+typedef struct policy_entry_t policy_entry_t;
+
+/**
+ * installed kernel policy.
+ */
+struct policy_entry_t {
+	/** 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;
+
+	/** List of SAs this policy is used by, ordered by priority */
+	linked_list_t *used_by;
+};
+
+/**
+ * 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;
+	INIT(policy,
+		.direction = dir,
+	);
+	u_int16_t port;
+	u_int8_t proto;
+
+	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 */
+	proto = max(src_ts->get_protocol(src_ts), dst_ts->get_protocol(dst_ts));
+	/* map the ports to ICMP type/code how the Linux kernel expects them, that
+	 * is, type in src, code in dst */
+	if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6)
+	{
+		port = max(policy->src.net->get_port(policy->src.net),
+				   policy->dst.net->get_port(policy->dst.net));
+		policy->src.net->set_port(policy->src.net,
+								  traffic_selector_icmp_type(port));
+		policy->dst.net->set_port(policy->dst.net,
+								  traffic_selector_icmp_code(port));
+	}
+	else if (!proto)
+	{
+		proto = IPSEC_PROTO_ANY;
+	}
+	policy->src.proto = policy->dst.proto = proto;
+
+	return policy;
+}
+
+/**
+ * Destroy a policy_entry_t object
+ */
+static void policy_entry_destroy(policy_entry_t *policy,
+								 private_kernel_pfkey_ipsec_t *this)
+{
+	if (policy->route)
+	{
+		route_entry_destroy(policy->route);
+	}
+	if (policy->used_by)
+	{
+		policy->used_by->invoke_function(policy->used_by,
+										(linked_list_invoke_t)policy_sa_destroy,
+										 &policy->direction, this);
+		policy->used_by->destroy(policy->used_by);
+	}
+	DESTROY_IF(policy->src.net);
+	DESTROY_IF(policy->dst.net);
+	free(policy);
+}
+
+/**
+ * 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;
+}
+
+/**
+ * Calculate the priority of a policy
+ */
+static inline u_int32_t get_priority(policy_entry_t *policy,
+									 policy_priority_t prio)
+{
+	u_int32_t priority = PRIO_BASE;
+	switch (prio)
+	{
+		case POLICY_PRIORITY_FALLBACK:
+			priority <<= 1;
+			/* fall-through */
+		case POLICY_PRIORITY_ROUTED:
+			priority <<= 1;
+			/* fall-through */
+		case POLICY_PRIORITY_DEFAULT:
+			priority <<= 1;
+			/* fall-trough */
+		case POLICY_PRIORITY_PASS:
+			break;
+	}
+	/* calculate priority based on selector size, small size = high prio */
+	priority -= policy->src.mask;
+	priority -= policy->dst.mask;
+	priority <<= 2; /* make some room for the two flags */
+	priority += policy->src.net->get_port(policy->src.net) ||
+				policy->dst.net->get_port(policy->dst.net) ?
+				0 : 2;
+	priority += policy->src.proto != IPSEC_PROTO_ANY ? 0 : 1;
+	return priority;
+}
+
+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_EXT_MAX,
+	"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 protocol identifier to the PF_KEY sa type
+ */
+static u_int8_t proto2satype(u_int8_t proto)
+{
+	switch (proto)
+	{
+		case IPPROTO_ESP:
+			return SADB_SATYPE_ESP;
+		case IPPROTO_AH:
+			return SADB_SATYPE_AH;
+		case IPPROTO_COMP:
+			return SADB_X_SATYPE_IPCOMP;
+		default:
+			return proto;
+	}
+}
+
+/**
+ * convert a PF_KEY sa type to a protocol identifier
+ */
+static u_int8_t satype2proto(u_int8_t satype)
+{
+	switch (satype)
+	{
+		case SADB_SATYPE_ESP:
+			return IPPROTO_ESP;
+		case SADB_SATYPE_AH:
+			return IPPROTO_AH;
+		case SADB_X_SATYPE_IPCOMP:
+			return IPPROTO_COMP;
+		default:
+			return satype;
+	}
+}
+
+/**
+ * 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;
+#ifdef HAVE_IPSEC_MODE_BEET
+		case MODE_BEET:
+			return IPSEC_MODE_BEET;
+#endif
+		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;
+#ifdef HAVE_IPSEC_DIR_FWD
+		case POLICY_FWD:
+			return IPSEC_DIR_FWD;
+#endif
+		default:
+			return IPSEC_DIR_INVALID;
+	}
+}
+
+/**
+ * convert the policy type to the one defined in ipsec.h
+ */
+static inline u_int16_t type2kernel(policy_type_t type)
+{
+	switch (type)
+	{
+		case POLICY_IPSEC:
+			return IPSEC_POLICY_IPSEC;
+		case POLICY_PASS:
+			return IPSEC_POLICY_NONE;
+		case POLICY_DROP:
+			return IPSEC_POLICY_DISCARD;
+	}
+	return type;
+}
+
+#ifdef SADB_X_MIGRATE
+/**
+ * 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;
+#ifdef HAVE_IPSEC_DIR_FWD
+		case IPSEC_DIR_FWD:
+			return POLICY_FWD;
+#endif
+		default:
+			return dir;
+	}
+}
+#endif /*SADB_X_MIGRATE*/
+
+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			},
+#ifdef SADB_X_EALG_AESCTR
+	{ENCR_AES_CTR,				SADB_X_EALG_AESCTR			},
+#endif
+/*  {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	}, */
+#ifdef SADB_X_EALG_AES_GCM_ICV8 /* assume the others are defined too */
+	{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	},
+#endif
+#ifdef SADB_X_EALG_CAMELLIACBC
+	{ENCR_CAMELLIA_CBC,			SADB_X_EALG_CAMELLIACBC		},
+#endif
+	{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,							}, */
+#ifdef SADB_X_AALG_AES_XCBC_MAC
+	{AUTH_AES_XCBC_96,			SADB_X_AALG_AES_XCBC_MAC,	},
+#endif
+	{END_OF_LIST,				0,							},
+};
+
+/**
+ * Algorithms for IPComp, unused yet
+ */
+static kernel_algorithm_t compression_algs[] = {
+/*	{IPCOMP_OUI,				0							}, */
+	{IPCOMP_DEFLATE,			SADB_X_CALG_DEFLATE			},
+#ifdef SADB_X_CALG_LZS
+	{IPCOMP_LZS,				SADB_X_CALG_LZS				},
+#endif
+#ifdef SADB_X_CALG_LZJH
+	{IPCOMP_LZJH,				SADB_X_CALG_LZJH			},
+#endif
+	{END_OF_LIST,				0							},
+};
+
+/**
+ * Look up a kernel algorithm ID and its key size
+ */
+static int lookup_algorithm(transform_type_t type, int ikev2)
+{
+	kernel_algorithm_t *list;
+	u_int16_t alg = 0;
+
+	switch (type)
+	{
+		case ENCRYPTION_ALGORITHM:
+			list = encryption_algs;
+			break;
+		case INTEGRITY_ALGORITHM:
+			list = integrity_algs;
+			break;
+		case COMPRESSION_ALGORITHM:
+			list = compression_algs;
+			break;
+		default:
+			return 0;
+	}
+	while (list->ikev2 != END_OF_LIST)
+	{
+		if (ikev2 == list->ikev2)
+		{
+			return list->kernel;
+		}
+		list++;
+	}
+	charon->kernel->lookup_algorithm(charon->kernel, ikev2, type, &alg, NULL);
+	return alg;
+}
+
+/**
+ * Helper to set a port in a sockaddr_t, the port has to be in host order
+ */
+static void set_port(sockaddr_t *addr, u_int16_t port)
+{
+	switch (addr->sa_family)
+	{
+		case AF_INET:
+		{
+			struct sockaddr_in *sin = (struct sockaddr_in*)addr;
+			sin->sin_port = htons(port);
+			break;
+		}
+		case AF_INET6:
+		{
+			struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)addr;
+			sin6->sin6_port = htons(port);
+			break;
+		}
+	}
+}
+
+/**
+ * Copy a host_t as sockaddr_t to the given memory location.
+ * @return		the number of bytes copied
+ */
+static size_t hostcpy(void *dest, host_t *host, bool include_port)
+{
+	sockaddr_t *addr = host->get_sockaddr(host), *dest_addr = dest;
+	socklen_t *len = host->get_sockaddr_len(host);
+
+	memcpy(dest, addr, *len);
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+	dest_addr->sa_len = *len;
+#endif
+	if (!include_port)
+	{
+		set_port(dest_addr, 0);
+	}
+	return *len;
+}
+
+/**
+ * add a host to the given sadb_msg
+ */
+static void add_addr_ext(struct sadb_msg *msg, host_t *host, u_int16_t type,
+						 u_int8_t proto, u_int8_t prefixlen, bool include_port)
+{
+	struct sadb_address *addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
+	size_t len;
+
+	addr->sadb_address_exttype = type;
+	addr->sadb_address_proto = proto;
+	addr->sadb_address_prefixlen = prefixlen;
+	len = hostcpy(addr + 1, host, include_port);
+	addr->sadb_address_len = PFKEY_LEN(sizeof(*addr) + len);
+	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;
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+	saddr->sa_len = len;
+#endif
+	addr->sadb_address_len = PFKEY_LEN(sizeof(*addr) + len);
+	PFKEY_EXT_ADD(msg, addr);
+}
+
+#ifdef HAVE_NATT
+/**
+ * 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(*nat_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(*nat_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(*nat_port));
+	nat_port->sadb_x_nat_t_port_port = htons(dst->get_port(dst));
+	PFKEY_EXT_ADD(msg, nat_port);
+}
+#endif /*HAVE_NATT*/
+
+/**
+ * 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;
+	u_int8_t proto;
+
+	proto = address->sadb_address_proto;
+	proto = proto == IPSEC_PROTO_ANY ? 0 : proto;
+
+	/* 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,
+											 proto, host->get_port(host),
+											 host->get_port(host) ?: 65535);
+	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)))
+	{
+		DBG3(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);
+
+	/* FIXME: our usage of sequence numbers is probably wrong. check RFC 2367,
+	 * in particular the behavior in response to an SADB_ACQUIRE. */
+	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)
+		{
+			DBG2(DBG_KNL, "received PF_KEY message with unexpected sequence "
+						  "number, was %d expected %d", msg->sadb_msg_seq,
+						  this->seq);
+			if (msg->sadb_msg_seq == 0)
+			{
+				/* FreeBSD and Mac OS X do this for the response to
+				 * SADB_X_SPDGET (but not for the response to SADB_GET).
+				 * FreeBSD: 'key_spdget' in /usr/src/sys/netipsec/key.c. */
+			}
+			else if (msg->sadb_msg_seq < this->seq)
+			{
+				continue;
+			}
+			else
+			{
+				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;
+	policy_sa_t *sa;
+
+	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 &&
+		policy->used_by->get_first(policy->used_by, (void**)&sa) == SUCCESS)
+	{
+		reqid = sa->sa->cfg.reqid;
+	}
+	else
+	{
+		DBG1(DBG_KNL, "received an SADB_ACQUIRE with policy id %d but no "
+					  "matching policy found", index);
+	}
+	this->mutex->unlock(this->mutex);
+
+	src_ts = sadb_address2ts(response.src);
+	dst_ts = sadb_address2ts(response.dst);
+
+	charon->kernel->acquire(charon->kernel, reqid, src_ts, dst_ts);
+}
+
+/**
+ * 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;
+	u_int8_t protocol;
+	u_int32_t spi;
+	host_t *dst;
+	bool hard;
+
+	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 = satype2proto(msg->sadb_msg_satype);
+	spi = response.sa->sadb_sa_spi;
+	hard = response.lft_hard != NULL;
+
+	if (protocol == IPPROTO_ESP || protocol == IPPROTO_AH)
+	{
+		dst = host_create_from_sockaddr((sockaddr_t*)(response.dst + 1));
+		if (dst)
+		{
+			charon->kernel->expire(charon->kernel, protocol, spi, dst, hard);
+			dst->destroy(dst);
+		}
+	}
+}
+
+#ifdef SADB_X_MIGRATE
+/**
+ * Process a SADB_X_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;
+
+	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)
+	{
+		charon->kernel->migrate(charon->kernel, reqid, src_ts, dst_ts, dir,
+								local, remote);
+	}
+	else
+	{
+		DESTROY_IF(src_ts);
+		DESTROY_IF(dst_ts);
+		DESTROY_IF(local);
+		DESTROY_IF(remote);
+	}
+}
+#endif /*SADB_X_MIGRATE*/
+
+#ifdef SADB_X_NAT_T_NEW_MAPPING
+/**
+ * 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;
+	sockaddr_t *sa;
+	host_t *dst, *new;
+
+	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;
+
+	if (satype2proto(msg->sadb_msg_satype) != IPPROTO_ESP)
+	{
+		return;
+	}
+
+	sa = (sockaddr_t*)(response.dst + 1);
+	dst = host_create_from_sockaddr(sa);
+	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);
+			break;
+		}
+		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);
+			break;
+		}
+		default:
+			break;
+	}
+	if (dst)
+	{
+		new = host_create_from_sockaddr(sa);
+		if (new)
+		{
+			charon->kernel->mapping(charon->kernel, IPPROTO_ESP, spi, dst, new);
+			new->destroy(new);
+		}
+		dst->destroy(dst);
+	}
+}
+#endif /*SADB_X_NAT_T_NEW_MAPPING*/
+
+/**
+ * Receives events from kernel
+ */
+static bool receive_events(private_kernel_pfkey_ipsec_t *this, int fd,
+						   watcher_event_t event)
+{
+	unsigned char buf[PFKEY_BUFFER_SIZE];
+	struct sadb_msg *msg = (struct sadb_msg*)buf;
+	int len;
+
+	len = recvfrom(this->socket_events, buf, sizeof(buf), MSG_DONTWAIT, NULL, 0);
+	if (len < 0)
+	{
+		switch (errno)
+		{
+			case EINTR:
+				/* interrupted, try again */
+				return TRUE;
+			case EAGAIN:
+				/* no data ready, select again */
+				return TRUE;
+			default:
+				DBG1(DBG_KNL, "unable to receive from PF_KEY event socket");
+				sleep(1);
+				return TRUE;
+		}
+	}
+
+	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 TRUE;
+	}
+	if (msg->sadb_msg_pid != 0)
+	{	/* not from kernel. not interested, try another one */
+		return TRUE;
+	}
+	if (msg->sadb_msg_len > len / PFKEY_ALIGNMENT)
+	{
+		DBG1(DBG_KNL, "buffer was too small to receive the complete "
+					  "PF_KEY message");
+		return TRUE;
+	}
+
+	switch (msg->sadb_msg_type)
+	{
+		case SADB_ACQUIRE:
+			process_acquire(this, msg);
+			break;
+		case SADB_EXPIRE:
+			process_expire(this, msg);
+			break;
+#ifdef SADB_X_MIGRATE
+		case SADB_X_MIGRATE:
+			process_migrate(this, msg);
+			break;
+#endif /*SADB_X_MIGRATE*/
+#ifdef SADB_X_NAT_T_NEW_MAPPING
+		case SADB_X_NAT_T_NEW_MAPPING:
+			process_mapping(this, msg);
+			break;
+#endif /*SADB_X_NAT_T_NEW_MAPPING*/
+		default:
+			break;
+	}
+
+	return TRUE;
+}
+
+/**
+ * Get an SPI for a specific protocol from the kernel.
+ */
+
+static status_t get_spi_internal(private_kernel_pfkey_ipsec_t *this,
+	host_t *src, host_t *dst, u_int8_t proto, u_int32_t min, u_int32_t max,
+	u_int32_t *spi)
+{
+	unsigned char request[PFKEY_BUFFER_SIZE];
+	struct sadb_msg *msg, *out;
+	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 = proto2satype(proto);
+	msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+	add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
+	add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
+
+	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 = min;
+	range->sadb_spirange_max = max;
+	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;
+}
+
+METHOD(kernel_ipsec_t, get_spi, status_t,
+	private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
+	u_int8_t protocol, u_int32_t *spi)
+{
+	if (get_spi_internal(this, src, dst, protocol,
+						 0xc0000000, 0xcFFFFFFF, spi) != SUCCESS)
+	{
+		DBG1(DBG_KNL, "unable to get SPI");
+		return FAILED;
+	}
+
+	DBG2(DBG_KNL, "got SPI %.8x", ntohl(*spi));
+	return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, get_cpi, status_t,
+	private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
+	u_int16_t *cpi)
+{
+	u_int32_t received_spi = 0;
+
+	DBG2(DBG_KNL, "getting CPI");
+
+	if (get_spi_internal(this, src, dst, IPPROTO_COMP,
+						 0x100, 0xEFFF, &received_spi) != SUCCESS)
+	{
+		DBG1(DBG_KNL, "unable to get CPI");
+		return FAILED;
+	}
+
+	*cpi = htons((u_int16_t)ntohl(received_spi));
+
+	DBG2(DBG_KNL, "got CPI %.4x", ntohs(*cpi));
+	return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, add_sa, status_t,
+	private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi,
+	u_int8_t protocol, u_int32_t reqid, mark_t mark, u_int32_t tfc,
+	lifetime_cfg_t *lifetime, 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, u_int32_t replay_window,
+	bool initiator, bool encap, bool esn, bool inbound, bool update,
+	linked_list_t *src_ts, linked_list_t *dst_ts)
+{
+	unsigned char request[PFKEY_BUFFER_SIZE];
+	struct sadb_msg *msg, *out;
+	struct sadb_sa *sa;
+	struct sadb_x_sa2 *sa2;
+	struct sadb_lifetime *lft;
+	struct sadb_key *key;
+	size_t len;
+
+	/* 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)
+	{
+		lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}};
+		add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark,
+			   tfc, &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED,
+			   chunk_empty, mode, ipcomp, 0, 0, FALSE, FALSE, FALSE, inbound,
+			   update, NULL, NULL);
+		ipcomp = IPCOMP_NONE;
+		/* use transport mode ESP SA, IPComp uses tunnel mode */
+		mode = MODE_TRANSPORT;
+	}
+
+	if (update)
+	{
+		/* As we didn't know the reqid during SPI allocation, we used reqid
+		 * zero. Unfortunately we can't SADB_UPDATE to the new reqid, hence we
+		 * have to delete the SPI allocation state manually. The reqid
+		 * selector does not count for that, therefore we have to delete
+		 * that state before installing the new SA to avoid deleting the
+		 * the new state after installing it. */
+		mark_t zeromark = {0, 0};
+
+		if (this->public.interface.del_sa(&this->public.interface,
+					src, dst, spi, protocol, 0, zeromark) != SUCCESS)
+		{
+			DBG1(DBG_KNL, "deleting SPI allocation SA failed");
+		}
+	}
+
+	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 = SADB_ADD;
+	msg->sadb_msg_satype = proto2satype(protocol);
+	msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+#ifdef __APPLE__
+	if (encap)
+	{
+		struct sadb_sa_2 *sa_2;
+		sa_2 = (struct sadb_sa_2*)PFKEY_EXT_ADD_NEXT(msg);
+		sa_2->sadb_sa_natt_port = dst->get_port(dst);
+		sa = &sa_2->sa;
+		sa->sadb_sa_flags |= SADB_X_EXT_NATT;
+		len = sizeof(struct sadb_sa_2);
+	}
+	else
+#endif
+	{
+		sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
+		len = sizeof(struct sadb_sa);
+	}
+	sa->sadb_sa_exttype = SADB_EXT_SA;
+	sa->sadb_sa_len = PFKEY_LEN(len);
+	sa->sadb_sa_spi = spi;
+	if (protocol == IPPROTO_COMP)
+	{
+		sa->sadb_sa_encrypt = lookup_algorithm(COMPRESSION_ALGORITHM, ipcomp);
+	}
+	else
+	{
+		/* Linux interprets sadb_sa_replay as number of packets/bits in the
+		 * replay window, whereas on BSD it's the size of the window in bytes */
+#ifdef __linux__
+		sa->sadb_sa_replay = min(replay_window, 32);
+#else
+		sa->sadb_sa_replay = (replay_window + 7) / 8;
+#endif
+		sa->sadb_sa_auth = lookup_algorithm(INTEGRITY_ALGORITHM, int_alg);
+		sa->sadb_sa_encrypt = lookup_algorithm(ENCRYPTION_ALGORITHM, 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);
+
+	add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
+	add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
+
+	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_allocations = lifetime->packets.rekey;
+	lft->sadb_lifetime_bytes = lifetime->bytes.rekey;
+	lft->sadb_lifetime_addtime = lifetime->time.rekey;
+	lft->sadb_lifetime_usetime = 0; /* we only use addtime */
+	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_allocations = lifetime->packets.life;
+	lft->sadb_lifetime_bytes = lifetime->bytes.life;
+	lft->sadb_lifetime_addtime = lifetime->time.life;
+	lft->sadb_lifetime_usetime = 0; /* we only use addtime */
+	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);
+	}
+
+#ifdef HAVE_NATT
+	if (encap)
+	{
+		add_encap_ext(msg, src, dst);
+	}
+#endif /*HAVE_NATT*/
+
+	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;
+}
+
+METHOD(kernel_ipsec_t, update_sa, status_t,
+	private_kernel_pfkey_ipsec_t *this, u_int32_t spi, u_int8_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, mark_t mark)
+{
+	unsigned char request[PFKEY_BUFFER_SIZE];
+	struct sadb_msg *msg, *out;
+	struct sadb_sa *sa;
+	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;
+	}
+
+	/* 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, mark);
+	}
+
+	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 = proto2satype(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. */
+	add_anyaddr_ext(msg, dst->get_family(dst), SADB_EXT_ADDRESS_SRC);
+	add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
+
+	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 = proto2satype(protocol);
+	msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+#ifdef __APPLE__
+	{
+		struct sadb_sa_2 *sa_2;
+		sa_2 = (struct sadb_sa_2*)PFKEY_EXT_ADD_NEXT(msg);
+		sa_2->sa.sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa_2));
+		memcpy(&sa_2->sa, response.sa, sizeof(struct sadb_sa));
+		if (encap)
+		{
+			sa_2->sadb_sa_natt_port = new_dst->get_port(new_dst);
+			sa_2->sa.sadb_sa_flags |= SADB_X_EXT_NATT;
+		}
+	}
+#else
+	PFKEY_EXT_COPY(msg, response.sa);
+#endif
+	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);
+	}
+
+#ifdef HAVE_NATT
+	if (new_encap)
+	{
+		add_encap_ext(msg, new_src, new_dst);
+	}
+#endif /*HAVE_NATT*/
+
+	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;
+}
+
+METHOD(kernel_ipsec_t, query_sa, status_t,
+	private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
+	u_int32_t spi, u_int8_t protocol, mark_t mark,
+	u_int64_t *bytes, u_int64_t *packets, time_t *time)
+{
+	unsigned char request[PFKEY_BUFFER_SIZE];
+	struct sadb_msg *msg, *out;
+	struct sadb_sa *sa;
+	pfkey_msg_t response;
+	size_t len;
+
+	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 = proto2satype(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 Linux Kernel doesn't care for the src address, but other systems do
+	 * (e.g. FreeBSD)
+	 */
+	add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
+	add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
+
+	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", ntohl(spi));
+		free(out);
+		return FAILED;
+	}
+	if (bytes)
+	{
+		*bytes = response.lft_current->sadb_lifetime_bytes;
+	}
+	if (packets)
+	{
+		/* at least on Linux and FreeBSD this contains the number of packets */
+		*packets = response.lft_current->sadb_lifetime_allocations;
+	}
+	if (time)
+	{
+#ifdef __APPLE__
+		/* OS X uses the "last" time of use in usetime */
+		*time = response.lft_current->sadb_lifetime_usetime;
+#else /* !__APPLE__ */
+		/* on Linux, sadb_lifetime_usetime is set to the "first" time of use,
+		 * which is actually correct according to PF_KEY. We have to query
+		 * policies for the last usetime. */
+		*time = 0;
+#endif /* !__APPLE__ */
+	}
+
+	free(out);
+	return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, del_sa, status_t,
+	private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
+	u_int32_t spi, u_int8_t protocol, u_int16_t cpi, mark_t mark)
+{
+	unsigned char request[PFKEY_BUFFER_SIZE];
+	struct sadb_msg *msg, *out;
+	struct sadb_sa *sa;
+	size_t len;
+
+	/* if IPComp was used, we first delete the additional IPComp SA */
+	if (cpi)
+	{
+		del_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0, mark);
+	}
+
+	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 = proto2satype(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 Linux Kernel doesn't care for the src address, but other systems do
+	 * (e.g. FreeBSD)
+	 */
+	add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
+	add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
+
+	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;
+}
+
+METHOD(kernel_ipsec_t, flush_sas, status_t,
+	private_kernel_pfkey_ipsec_t *this)
+{
+	unsigned char request[PFKEY_BUFFER_SIZE];
+	struct sadb_msg *msg, *out;
+	struct {
+		u_int8_t proto;
+		char *name;
+	} protos[] = {
+		{ SADB_SATYPE_AH, "AH" },
+		{ SADB_SATYPE_ESP, "ESP" },
+		{ SADB_X_SATYPE_IPCOMP, "IPComp" },
+	};
+	size_t len;
+	int i;
+
+	memset(&request, 0, sizeof(request));
+
+	msg = (struct sadb_msg*)request;
+	msg->sadb_msg_version = PF_KEY_V2;
+	msg->sadb_msg_type = SADB_FLUSH;
+	msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+	for (i = 0; i < countof(protos); i++)
+	{
+		DBG2(DBG_KNL, "flushing all %s SAD entries", protos[i].name);
+
+		msg->sadb_msg_satype = protos[i].proto;
+		if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+		{
+			DBG1(DBG_KNL, "unable to flush %s SAD entries", protos[i].name);
+			return FAILED;
+		}
+		else if (out->sadb_msg_errno)
+		{
+			DBG1(DBG_KNL, "unable to flush %s SAD entries: %s (%d)",
+				 protos[i].name, strerror(out->sadb_msg_errno),
+				 out->sadb_msg_errno);
+			free(out);
+			return FAILED;
+		}
+		free(out);
+	}
+	return SUCCESS;
+}
+
+/**
+ * Add an explicit exclude route to a routing entry
+ */
+static void add_exclude_route(private_kernel_pfkey_ipsec_t *this,
+							  route_entry_t *route, host_t *src, host_t *dst)
+{
+	enumerator_t *enumerator;
+	exclude_route_t *exclude;
+	host_t *gtw;
+
+	enumerator = this->excludes->create_enumerator(this->excludes);
+	while (enumerator->enumerate(enumerator, &exclude))
+	{
+		if (dst->ip_equals(dst, exclude->dst))
+		{
+			route->exclude = exclude;
+			exclude->refs++;
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	if (!route->exclude)
+	{
+		DBG2(DBG_KNL, "installing new exclude route for %H src %H", dst, src);
+		gtw = charon->kernel->get_nexthop(charon->kernel, dst, -1, NULL);
+		if (gtw)
+		{
+			char *if_name = NULL;
+
+			if (charon->kernel->get_interface(charon->kernel, src, &if_name) &&
+				charon->kernel->add_route(charon->kernel,
+									dst->get_address(dst),
+									dst->get_family(dst) == AF_INET ? 32 : 128,
+									gtw, src, if_name) == SUCCESS)
+			{
+				INIT(exclude,
+					.dst = dst->clone(dst),
+					.src = src->clone(src),
+					.gtw = gtw->clone(gtw),
+					.refs = 1,
+				);
+				route->exclude = exclude;
+				this->excludes->insert_last(this->excludes, exclude);
+			}
+			else
+			{
+				DBG1(DBG_KNL, "installing exclude route for %H failed", dst);
+			}
+			gtw->destroy(gtw);
+			free(if_name);
+		}
+		else
+		{
+			DBG1(DBG_KNL, "gateway lookup for for %H failed", dst);
+		}
+	}
+}
+
+/**
+ * Remove an exclude route attached to a routing entry
+ */
+static void remove_exclude_route(private_kernel_pfkey_ipsec_t *this,
+								 route_entry_t *route)
+{
+	if (route->exclude)
+	{
+		enumerator_t *enumerator;
+		exclude_route_t *exclude;
+		bool removed = FALSE;
+		host_t *dst;
+
+		enumerator = this->excludes->create_enumerator(this->excludes);
+		while (enumerator->enumerate(enumerator, &exclude))
+		{
+			if (route->exclude == exclude)
+			{
+				if (--exclude->refs == 0)
+				{
+					this->excludes->remove_at(this->excludes, enumerator);
+					removed = TRUE;
+					break;
+				}
+			}
+		}
+		enumerator->destroy(enumerator);
+
+		if (removed)
+		{
+			char *if_name = NULL;
+
+			dst = route->exclude->dst;
+			DBG2(DBG_KNL, "uninstalling exclude route for %H src %H",
+				 dst, route->exclude->src);
+			if (charon->kernel->get_interface(
+									charon->kernel,
+									route->exclude->src, &if_name) &&
+				charon->kernel->del_route(charon->kernel,
+									dst->get_address(dst),
+									dst->get_family(dst) == AF_INET ? 32 : 128,
+									route->exclude->gtw, route->exclude->src,
+									if_name) != SUCCESS)
+			{
+				DBG1(DBG_KNL, "uninstalling exclude route for %H failed", dst);
+			}
+			exclude_route_destroy(route->exclude);
+			free(if_name);
+		}
+		route->exclude = NULL;
+	}
+}
+
+/**
+ * Try to install a route to the given inbound policy
+ */
+static bool install_route(private_kernel_pfkey_ipsec_t *this,
+						  policy_entry_t *policy, policy_sa_in_t *in)
+{
+	route_entry_t *route, *old;
+	host_t *host, *src, *dst;
+	bool is_virtual;
+
+	if (charon->kernel->get_address_by_ts(charon->kernel, in->dst_ts, &host,
+										  &is_virtual) != SUCCESS)
+	{
+		return FALSE;
+	}
+
+	/* switch src/dst, as we handle an IN policy */
+	src = in->generic.sa->dst;
+	dst = in->generic.sa->src;
+
+	INIT(route,
+		.prefixlen = policy->src.mask,
+		.src_ip = host,
+		.dst_net = chunk_clone(policy->src.net->get_address(policy->src.net)),
+	);
+
+	if (!dst->is_anyaddr(dst))
+	{
+		route->gateway = charon->kernel->get_nexthop(charon->kernel, dst, -1,
+													 src);
+
+		/* if the IP is virtual, we install the route over the interface it has
+		 * been installed on. Otherwise we use the interface we use for IKE, as
+		 * this is required for example on Linux. */
+		if (is_virtual)
+		{
+			src = route->src_ip;
+		}
+	}
+	else
+	{	/* for shunt policies */
+		route->gateway = charon->kernel->get_nexthop(charon->kernel,
+											policy->src.net, policy->src.mask,
+											route->src_ip);
+
+		/* we don't have a source address, use the address we found */
+		src = route->src_ip;
+	}
+
+	/* get interface for route, using source address */
+	if (!charon->kernel->get_interface(charon->kernel, src, &route->if_name))
+	{
+		route_entry_destroy(route);
+		return FALSE;
+	}
+
+	if (policy->route)
+	{
+		old = policy->route;
+
+		if (route_entry_equals(old, route))
+		{	/* such a route already exists */
+			route_entry_destroy(route);
+			return TRUE;
+		}
+		/* uninstall previously installed route */
+		if (charon->kernel->del_route(charon->kernel, old->dst_net,
+									  old->prefixlen, old->gateway,
+									  old->src_ip, old->if_name) != SUCCESS)
+		{
+			DBG1(DBG_KNL, "error uninstalling route installed with policy "
+				 "%R === %R %N", in->src_ts, in->dst_ts,
+				policy_dir_names, policy->direction);
+		}
+		route_entry_destroy(old);
+		policy->route = NULL;
+	}
+
+	/* if remote traffic selector covers the IKE peer, add an exclude route */
+	if (charon->kernel->get_features(charon->kernel) & KERNEL_REQUIRE_EXCLUDE_ROUTE)
+	{
+		if (in->src_ts->is_host(in->src_ts, dst))
+		{
+			DBG1(DBG_KNL, "can't install route for %R === %R %N, conflicts "
+				 "with IKE traffic", in->src_ts, in->dst_ts, policy_dir_names,
+				 policy->direction);
+			route_entry_destroy(route);
+			return FALSE;
+		}
+		if (in->src_ts->includes(in->src_ts, dst))
+		{
+			add_exclude_route(this, route, in->generic.sa->dst, dst);
+		}
+	}
+
+	DBG2(DBG_KNL, "installing route: %R via %H src %H dev %s",
+		 in->src_ts, route->gateway, route->src_ip, route->if_name);
+
+	switch (charon->kernel->add_route(charon->kernel, route->dst_net,
+									  route->prefixlen, route->gateway,
+									  route->src_ip, route->if_name))
+	{
+		case ALREADY_DONE:
+			/* route exists, do not uninstall */
+			remove_exclude_route(this, route);
+			route_entry_destroy(route);
+			return TRUE;
+		case SUCCESS:
+			/* cache the installed route */
+			policy->route = route;
+			return TRUE;
+		default:
+			DBG1(DBG_KNL, "installing route failed: %R via %H src %H dev %s",
+				 in->src_ts, route->gateway, route->src_ip, route->if_name);
+			remove_exclude_route(this, route);
+			route_entry_destroy(route);
+			return FALSE;
+	}
+}
+
+/**
+ * Add or update a policy in the kernel.
+ *
+ * Note: The mutex has to be locked when entering this function.
+ */
+static status_t add_policy_internal(private_kernel_pfkey_ipsec_t *this,
+	policy_entry_t *policy, policy_sa_t *mapping, bool update)
+{
+	unsigned char request[PFKEY_BUFFER_SIZE];
+	struct sadb_msg *msg, *out;
+	struct sadb_x_policy *pol;
+	struct sadb_x_ipsecrequest *req;
+	ipsec_sa_t *ipsec = mapping->sa;
+	pfkey_msg_t response;
+	size_t len;
+	ipsec_mode_t proto_mode;
+	status_t status;
+
+	memset(&request, 0, sizeof(request));
+
+	msg = (struct sadb_msg*)request;
+	msg->sadb_msg_version = PF_KEY_V2;
+	msg->sadb_msg_type = update ? 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(policy->direction);
+	pol->sadb_x_policy_type = type2kernel(mapping->type);
+#ifdef HAVE_STRUCT_SADB_X_POLICY_SADB_X_POLICY_PRIORITY
+	pol->sadb_x_policy_priority = mapping->priority;
+#endif
+
+	/* one or more sadb_x_ipsecrequest extensions are added to the
+	 * sadb_x_policy extension */
+	proto_mode = ipsec->cfg.mode;
+
+	req = (struct sadb_x_ipsecrequest*)(pol + 1);
+
+	if (ipsec->cfg.ipcomp.transform != IPCOMP_NONE)
+	{
+		req->sadb_x_ipsecrequest_proto = IPPROTO_COMP;
+
+		/* !!! the length here 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(ipsec->cfg.mode);
+		req->sadb_x_ipsecrequest_reqid = ipsec->cfg.reqid;
+		req->sadb_x_ipsecrequest_level = (policy->direction == POLICY_OUT) ?
+										  IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_USE;
+		if (ipsec->cfg.mode == MODE_TUNNEL)
+		{
+			len = hostcpy(req + 1, ipsec->src, FALSE);
+			req->sadb_x_ipsecrequest_len += len;
+			len = hostcpy((char*)(req + 1) + len, ipsec->dst, FALSE);
+			req->sadb_x_ipsecrequest_len += len;
+			/* use transport mode for other SAs */
+			proto_mode = MODE_TRANSPORT;
+		}
+
+		pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len);
+		req = (struct sadb_x_ipsecrequest*)((char*)(req) +
+											req->sadb_x_ipsecrequest_len);
+	}
+
+	req->sadb_x_ipsecrequest_proto = ipsec->cfg.esp.use ? IPPROTO_ESP
+														: IPPROTO_AH;
+	/* !!! the length here 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(proto_mode);
+	req->sadb_x_ipsecrequest_reqid = ipsec->cfg.reqid;
+	req->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
+	if (proto_mode == MODE_TUNNEL)
+	{
+		len = hostcpy(req + 1, ipsec->src, FALSE);
+		req->sadb_x_ipsecrequest_len += len;
+		len = hostcpy((char*)(req + 1) + len, ipsec->dst, FALSE);
+		req->sadb_x_ipsecrequest_len += len;
+	}
+
+	pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len);
+	PFKEY_EXT_ADD(msg, pol);
+
+	add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto,
+				 policy->src.mask, TRUE);
+	add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto,
+				 policy->dst.mask, TRUE);
+
+#ifdef __FreeBSD__
+	{	/* on FreeBSD a lifetime has to be defined to be able to later query
+		 * the current use time. */
+		struct sadb_lifetime *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 = LONG_MAX;
+		PFKEY_EXT_ADD(msg, lft);
+	}
+#endif
+
+	this->mutex->unlock(this->mutex);
+
+	status = pfkey_send(this, msg, &out, &len);
+	if (status == SUCCESS && !update && out->sadb_msg_errno == EEXIST)
+	{
+		DBG1(DBG_KNL, "policy already exists, try to update it");
+		free(out);
+		msg->sadb_msg_type = SADB_X_SPDUPDATE;
+		status = pfkey_send(this, msg, &out, &len);
+	}
+	if (status != SUCCESS)
+	{
+		return FAILED;
+	}
+	else if (out->sadb_msg_errno)
+	{
+		DBG1(DBG_KNL, "unable to %s policy: %s (%d)",
+					   update ? "update" : "add", 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 %s policy: parsing response from kernel "
+					  "failed", update ? "update" : "add");
+		free(out);
+		return FAILED;
+	}
+
+	/* we try to find the policy again and update the kernel index */
+	this->mutex->lock(this->mutex);
+	if (this->policies->find_first(this->policies, NULL,
+								  (void**)&policy) != SUCCESS)
+	{
+		DBG2(DBG_KNL, "unable to update index, the policy is already gone, "
+					  "ignoring");
+		this->mutex->unlock(this->mutex);
+		free(out);
+		return SUCCESS;
+	}
+	policy->index = response.x_policy->sadb_x_policy_id;
+	free(out);
+
+	/* install a route, if:
+	 * - this is an inbound policy (to just get one for each child)
+	 * - we are in tunnel mode or install a bypass policy
+	 * - routing is not disabled via strongswan.conf
+	 */
+	if (policy->direction == POLICY_IN && this->install_routes &&
+		(mapping->type != POLICY_IPSEC || ipsec->cfg.mode != MODE_TRANSPORT))
+	{
+		install_route(this, policy, (policy_sa_in_t*)mapping);
+	}
+	this->mutex->unlock(this->mutex);
+	return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, add_policy, status_t,
+	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, policy_type_t type, ipsec_sa_cfg_t *sa,
+	mark_t mark, policy_priority_t priority)
+{
+	policy_entry_t *policy, *found = NULL;
+	policy_sa_t *assigned_sa, *current_sa;
+	enumerator_t *enumerator;
+	bool update = TRUE;
+
+	if (dir2kernel(direction) == IPSEC_DIR_INVALID)
+	{	/* FWD policies are not supported on all platforms */
+		return SUCCESS;
+	}
+
+	/* 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, this);
+		policy = found;
+	}
+	else
+	{	/* use the new one, if we have no such policy */
+		this->policies->insert_first(this->policies, policy);
+		policy->used_by = linked_list_create();
+	}
+
+	/* cache the assigned IPsec SA */
+	assigned_sa = policy_sa_create(this, direction, type, src, dst, src_ts,
+								   dst_ts, sa);
+	assigned_sa->priority = get_priority(policy, priority);
+
+	/* insert the SA according to its priority */
+	enumerator = policy->used_by->create_enumerator(policy->used_by);
+	while (enumerator->enumerate(enumerator, (void**)&current_sa))
+	{
+		if (current_sa->priority >= assigned_sa->priority)
+		{
+			break;
+		}
+		update = FALSE;
+	}
+	policy->used_by->insert_before(policy->used_by, enumerator, assigned_sa);
+	enumerator->destroy(enumerator);
+
+	if (!update)
+	{	/* we don't update the policy if the priority is lower than that of the
+		 * currently installed one */
+		this->mutex->unlock(this->mutex);
+		return SUCCESS;
+	}
+
+	DBG2(DBG_KNL, "%s policy %R === %R %N",
+				   found ? "updating" : "adding", src_ts, dst_ts,
+				   policy_dir_names, direction);
+
+	if (add_policy_internal(this, policy, assigned_sa, found) != SUCCESS)
+	{
+		DBG1(DBG_KNL, "unable to %s policy %R === %R %N",
+					   found ? "update" : "add", src_ts, dst_ts,
+					   policy_dir_names, direction);
+		return FAILED;
+	}
+	return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, query_policy, status_t,
+	private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts,
+	traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+	time_t *use_time)
+{
+	unsigned char request[PFKEY_BUFFER_SIZE];
+	struct sadb_msg *msg, *out;
+	struct sadb_x_policy *pol;
+	policy_entry_t *policy, *found = NULL;
+	pfkey_msg_t response;
+	size_t len;
+
+	if (dir2kernel(direction) == IPSEC_DIR_INVALID)
+	{	/* FWD policies are not supported on all platforms */
+		return NOT_FOUND;
+	}
+
+	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)
+	{
+		DBG1(DBG_KNL, "querying policy %R === %R %N failed, not found", src_ts,
+					   dst_ts, policy_dir_names, direction);
+		policy_entry_destroy(policy, this);
+		this->mutex->unlock(this->mutex);
+		return NOT_FOUND;
+	}
+	policy_entry_destroy(policy, this);
+	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);
+
+	add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto,
+				 policy->src.mask, TRUE);
+	add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto,
+				 policy->dst.mask, TRUE);
+
+	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;
+	}
+	else if (response.lft_current == NULL)
+	{
+		DBG2(DBG_KNL, "unable to query policy %R === %R %N: kernel reports no "
+					  "use time", src_ts, dst_ts, policy_dir_names, direction);
+		free(out);
+		return FAILED;
+	}
+
+	/* we need the monotonic time, but the kernel returns system time. */
+	if (response.lft_current->sadb_lifetime_usetime)
+	{
+		*use_time = time_monotonic(NULL) -
+					(time(NULL) - response.lft_current->sadb_lifetime_usetime);
+	}
+	else
+	{
+		*use_time = 0;
+	}
+	free(out);
+	return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, del_policy, status_t,
+	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, policy_type_t type, ipsec_sa_cfg_t *sa,
+	mark_t mark, policy_priority_t prio)
+{
+	unsigned char request[PFKEY_BUFFER_SIZE];
+	struct sadb_msg *msg, *out;
+	struct sadb_x_policy *pol;
+	policy_entry_t *policy, *found = NULL;
+	policy_sa_t *mapping, *to_remove = NULL;
+	enumerator_t *enumerator;
+	bool first = TRUE, is_installed = TRUE;
+	u_int32_t priority;
+	size_t len;
+	ipsec_sa_t assigned_sa = {
+		.src = src,
+		.dst = dst,
+		.cfg = *sa,
+	};
+
+	if (dir2kernel(direction) == IPSEC_DIR_INVALID)
+	{	/* FWD policies are not supported on all platforms */
+		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)
+	{
+		DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts,
+					   dst_ts, policy_dir_names, direction);
+		policy_entry_destroy(policy, this);
+		this->mutex->unlock(this->mutex);
+		return NOT_FOUND;
+	}
+	policy_entry_destroy(policy, this);
+	policy = found;
+
+	/* remove mapping to SA by reqid and priority, if multiple match, which
+	 * could happen when rekeying due to an address change, remove the oldest */
+	priority = get_priority(policy, prio);
+	enumerator = policy->used_by->create_enumerator(policy->used_by);
+	while (enumerator->enumerate(enumerator, (void**)&mapping))
+	{
+		if (priority == mapping->priority &&
+			ipsec_sa_equals(mapping->sa, &assigned_sa))
+		{
+			to_remove = mapping;
+			is_installed = first;
+		}
+		else if (priority < mapping->priority)
+		{
+			break;
+		}
+		first = FALSE;
+	}
+	enumerator->destroy(enumerator);
+	if (!to_remove)
+	{	/* sanity check */
+		this->mutex->unlock(this->mutex);
+		return SUCCESS;
+	}
+	policy->used_by->remove(policy->used_by, to_remove, NULL);
+	mapping = to_remove;
+
+	if (policy->used_by->get_count(policy->used_by) > 0)
+	{	/* policy is used by more SAs, keep in kernel */
+		DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
+		policy_sa_destroy(mapping, &direction, this);
+
+		if (!is_installed)
+		{	/* no need to update as the policy was not installed for this SA */
+			this->mutex->unlock(this->mutex);
+			return SUCCESS;
+		}
+
+		DBG2(DBG_KNL, "updating policy %R === %R %N", src_ts, dst_ts,
+					   policy_dir_names, direction);
+		policy->used_by->get_first(policy->used_by, (void**)&mapping);
+		if (add_policy_internal(this, policy, mapping, TRUE) != SUCCESS)
+		{
+			DBG1(DBG_KNL, "unable to update policy %R === %R %N",
+						   src_ts, dst_ts, policy_dir_names, direction);
+			return FAILED;
+		}
+		return SUCCESS;
+	}
+
+	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 = type2kernel(mapping->type);
+	PFKEY_EXT_ADD(msg, pol);
+
+	add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto,
+				 policy->src.mask, TRUE);
+	add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto,
+				 policy->dst.mask, TRUE);
+
+	if (policy->route)
+	{
+		route_entry_t *route = policy->route;
+		if (charon->kernel->del_route(charon->kernel, 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);
+		}
+		remove_exclude_route(this, route);
+	}
+
+	this->policies->remove(this->policies, found, NULL);
+	policy_sa_destroy(mapping, &direction, this);
+	policy_entry_destroy(policy, this);
+	this->mutex->unlock(this->mutex);
+
+	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);
+	return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, flush_policies, status_t,
+	private_kernel_pfkey_ipsec_t *this)
+{
+	unsigned char request[PFKEY_BUFFER_SIZE];
+	struct sadb_msg *msg, *out;
+	size_t len;
+
+	memset(&request, 0, sizeof(request));
+
+	DBG2(DBG_KNL, "flushing all policies from SPD");
+
+	msg = (struct sadb_msg*)request;
+	msg->sadb_msg_version = PF_KEY_V2;
+	msg->sadb_msg_type = SADB_X_SPDFLUSH;
+	msg->sadb_msg_satype = SADB_SATYPE_UNSPEC;
+	msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
+
+	if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+	{
+		DBG1(DBG_KNL, "unable to flush SPD entries");
+		return FAILED;
+	}
+	else if (out->sadb_msg_errno)
+	{
+		DBG1(DBG_KNL, "unable to flush SPD entries: %s (%d)",
+					   strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+		free(out);
+		return FAILED;
+	}
+	free(out);
+	return SUCCESS;
+}
+
+/**
+ * Register a socket for ACQUIRE/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;
+}
+
+METHOD(kernel_ipsec_t, bypass_socket, bool,
+	private_kernel_pfkey_ipsec_t *this, int fd, int family)
+{
+	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:
+			return FALSE;
+	}
+
+	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));
+		return FALSE;
+	}
+	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));
+		return FALSE;
+	}
+	return TRUE;
+}
+
+METHOD(kernel_ipsec_t, enable_udp_decap, bool,
+	private_kernel_pfkey_ipsec_t *this, int fd, int family, u_int16_t port)
+{
+#ifndef __APPLE__
+	int type = UDP_ENCAP_ESPINUDP;
+
+	if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
+	{
+		DBG1(DBG_KNL, "unable to set UDP_ENCAP: %s", strerror(errno));
+		return FALSE;
+	}
+#else /* __APPLE__ */
+	int intport = port;
+
+	if (sysctlbyname("net.inet.ipsec.esp_port", NULL, NULL, &intport,
+					 sizeof(intport)) != 0)
+	{
+		DBG1(DBG_KNL, "could not set net.inet.ipsec.esp_port to %d: %s",
+			 port, strerror(errno));
+		return FALSE;
+	}
+#endif /* __APPLE__ */
+
+	return TRUE;
+}
+
+METHOD(kernel_ipsec_t, destroy, void,
+	private_kernel_pfkey_ipsec_t *this)
+{
+	if (this->socket > 0)
+	{
+		close(this->socket);
+	}
+	if (this->socket_events > 0)
+	{
+		lib->watcher->remove(lib->watcher, this->socket_events);
+		close(this->socket_events);
+	}
+	this->policies->invoke_function(this->policies,
+								   (linked_list_invoke_t)policy_entry_destroy,
+									this);
+	this->policies->destroy(this->policies);
+	this->excludes->destroy(this->excludes);
+	this->sas->destroy(this->sas);
+	this->mutex->destroy(this->mutex);
+	this->mutex_pfkey->destroy(this->mutex_pfkey);
+	free(this);
+}
+
+/*
+ * Described in header.
+ */
+kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create()
+{
+	private_kernel_pfkey_ipsec_t *this;
+	bool register_for_events = TRUE;
+	int rcv_buffer;
+
+	INIT(this,
+		.public = {
+			.interface = {
+				.get_spi = _get_spi,
+				.get_cpi = _get_cpi,
+				.add_sa  = _add_sa,
+				.update_sa = _update_sa,
+				.query_sa = _query_sa,
+				.del_sa = _del_sa,
+				.flush_sas = _flush_sas,
+				.add_policy = _add_policy,
+				.query_policy = _query_policy,
+				.del_policy = _del_policy,
+				.flush_policies = _flush_policies,
+				.bypass_socket = _bypass_socket,
+				.enable_udp_decap = _enable_udp_decap,
+				.destroy = _destroy,
+			},
+		},
+		.policies = linked_list_create(),
+		.excludes = linked_list_create(),
+		.sas = hashtable_create((hashtable_hash_t)ipsec_sa_hash,
+								(hashtable_equals_t)ipsec_sa_equals, 32),
+		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+		.mutex_pfkey = mutex_create(MUTEX_TYPE_DEFAULT),
+		.install_routes = lib->settings->get_bool(lib->settings,
+												  "%s.install_routes", TRUE,
+												  lib->ns),
+	);
+
+	if (streq(lib->ns, "starter"))
+	{	/* starter has no threads, so we do not register for kernel events */
+		register_for_events = FALSE;
+	}
+
+	/* create a PF_KEY socket to communicate with the kernel */
+	this->socket = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
+	if (this->socket <= 0)
+	{
+		DBG1(DBG_KNL, "unable to create PF_KEY socket");
+		destroy(this);
+		return NULL;
+	}
+
+	if (register_for_events)
+	{
+		/* create a PF_KEY socket for ACQUIRE & EXPIRE */
+		this->socket_events = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
+		if (this->socket_events <= 0)
+		{
+			DBG1(DBG_KNL, "unable to create PF_KEY event socket");
+			destroy(this);
+			return NULL;
+		}
+
+		rcv_buffer = lib->settings->get_int(lib->settings,
+					"%s.plugins.kernel-pfkey.events_buffer_size", 0, lib->ns);
+		if (rcv_buffer > 0)
+		{
+			if (setsockopt(this->socket_events, SOL_SOCKET, SO_RCVBUF,
+						   &rcv_buffer, sizeof(rcv_buffer)) == -1)
+			{
+				DBG1(DBG_KNL, "unable to set receive buffer size on PF_KEY "
+					 "event socket: %s", strerror(errno));
+			}
+		}
+
+		/* register the event socket */
+		if (register_pfkey_socket(this, SADB_SATYPE_ESP) != SUCCESS ||
+			register_pfkey_socket(this, SADB_SATYPE_AH) != SUCCESS)
+		{
+			DBG1(DBG_KNL, "unable to register PF_KEY event socket");
+			destroy(this);
+			return NULL;
+		}
+
+		lib->watcher->add(lib->watcher, this->socket_events, WATCHER_READ,
+						  (watcher_cb_t)receive_events, this);
+	}
+
+	return &this->public;
+}
diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.h b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.h
similarity index 100%
rename from src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.h
rename to src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.h
diff --git a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.c b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.c
new file mode 100644
index 0000000..d49fe24
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.c
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+
+#include "kernel_pfkey_plugin.h"
+
+#include "kernel_pfkey_ipsec.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;
+};
+
+METHOD(plugin_t, get_name, char*,
+	private_kernel_pfkey_plugin_t *this)
+{
+	return "kernel-pfkey";
+}
+
+METHOD(plugin_t, get_features, int,
+	private_kernel_pfkey_plugin_t *this, plugin_feature_t *features[])
+{
+	static plugin_feature_t f[] = {
+		PLUGIN_CALLBACK(kernel_ipsec_register, kernel_pfkey_ipsec_create),
+			PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"),
+	};
+	*features = f;
+	return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+	private_kernel_pfkey_plugin_t *this)
+{
+	free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *kernel_pfkey_plugin_create()
+{
+	private_kernel_pfkey_plugin_t *this;
+
+	if (!lib->caps->check(lib->caps, CAP_NET_ADMIN))
+	{	/* required to open PF_KEY sockets */
+		DBG1(DBG_KNL, "kernel-pfkey plugin requires CAP_NET_ADMIN capability");
+		return NULL;
+	}
+
+	INIT(this,
+		.public = {
+			.plugin = {
+				.get_name = _get_name,
+				.get_features = _get_features,
+				.destroy = _destroy,
+			},
+		},
+	);
+
+	return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.h b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.h
new file mode 100644
index 0000000..ecccc63
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+/**
+ * @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;
+};
+
+#endif /** KERNEL_PFKEY_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_pfroute/Makefile.am b/src/libcharon/plugins/kernel_pfroute/Makefile.am
new file mode 100644
index 0000000..51047e3
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfroute/Makefile.am
@@ -0,0 +1,19 @@
+AM_CPPFLAGS = \
+	-I${linux_headers} \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+	$(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-kernel-pfroute.la
+else
+plugin_LTLIBRARIES = libstrongswan-kernel-pfroute.la
+endif
+
+libstrongswan_kernel_pfroute_la_SOURCES = \
+	kernel_pfroute_plugin.h kernel_pfroute_plugin.c \
+	kernel_pfroute_net.h kernel_pfroute_net.c
+
+libstrongswan_kernel_pfroute_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/kernel_pfroute/Makefile.in b/src/libcharon/plugins/kernel_pfroute/Makefile.in
new file mode 100644
index 0000000..77d83cb
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfroute/Makefile.in
@@ -0,0 +1,782 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 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.
+
+ at SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@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/libcharon/plugins/kernel_pfroute
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+	$(top_srcdir)/m4/config/ltoptions.m4 \
+	$(top_srcdir)/m4/config/ltsugar.m4 \
+	$(top_srcdir)/m4/config/ltversion.m4 \
+	$(top_srcdir)/m4/config/lt~obsolete.m4 \
+	$(top_srcdir)/m4/macros/split-package-version.m4 \
+	$(top_srcdir)/m4/macros/with.m4 \
+	$(top_srcdir)/m4/macros/enable-disable.m4 \
+	$(top_srcdir)/m4/macros/add-plugin.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_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 = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_kernel_pfroute_la_LIBADD =
+am_libstrongswan_kernel_pfroute_la_OBJECTS = kernel_pfroute_plugin.lo \
+	kernel_pfroute_net.lo
+libstrongswan_kernel_pfroute_la_OBJECTS =  \
+	$(am_libstrongswan_kernel_pfroute_la_OBJECTS)
+AM_V_lt = $(am__v_lt_ at AM_V@)
+am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+libstrongswan_kernel_pfroute_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) \
+	$(libstrongswan_kernel_pfroute_la_LDFLAGS) $(LDFLAGS) -o $@
+ at MONOLITHIC_FALSE@am_libstrongswan_kernel_pfroute_la_rpath = -rpath \
+ at MONOLITHIC_FALSE@	$(plugindir)
+ at MONOLITHIC_TRUE@am_libstrongswan_kernel_pfroute_la_rpath =
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_ at AM_V@)
+am__v_CC_ = $(am__v_CC_ at AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_ at AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_ at AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(libstrongswan_kernel_pfroute_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_kernel_pfroute_la_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GEM = @GEM@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
+PTHREADLIB = @PTHREADLIB@
+PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+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_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+	-I${linux_headers} \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+	$(PLUGIN_CFLAGS)
+
+ at MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-kernel-pfroute.la
+ at MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-kernel-pfroute.la
+libstrongswan_kernel_pfroute_la_SOURCES = \
+	kernel_pfroute_plugin.h kernel_pfroute_plugin.c \
+	kernel_pfroute_net.h kernel_pfroute_net.c
+
+libstrongswan_kernel_pfroute_la_LDFLAGS = -module -avoid-version
+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 ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_pfroute/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_pfroute/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
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+	}
+
+uninstall-pluginLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+	done
+
+clean-pluginLTLIBRARIES:
+	-test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+	@list='$(plugin_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+
+libstrongswan-kernel-pfroute.la: $(libstrongswan_kernel_pfroute_la_OBJECTS) $(libstrongswan_kernel_pfroute_la_DEPENDENCIES) $(EXTRA_libstrongswan_kernel_pfroute_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(libstrongswan_kernel_pfroute_la_LINK) $(am_libstrongswan_kernel_pfroute_la_rpath) $(libstrongswan_kernel_pfroute_la_OBJECTS) $(libstrongswan_kernel_pfroute_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_pfroute_net.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_pfroute_plugin.Plo at am__quote@
+
+.c.o:
+ at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+ at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+ at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+ at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+ at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+ at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+ at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+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 "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$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:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-noinstLTLIBRARIES \
+	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
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+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 TAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+	cscopelist-am ctags ctags-am 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 tags-am 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/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c
new file mode 100644
index 0000000..4eebdfd
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c
@@ -0,0 +1,1902 @@
+/*
+ * Copyright (C) 2009-2013 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.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <ifaddrs.h>
+#include <net/route.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "kernel_pfroute_net.h"
+
+#include <daemon.h>
+#include <utils/debug.h>
+#include <networking/host.h>
+#include <networking/tun_device.h>
+#include <threading/thread.h>
+#include <threading/mutex.h>
+#include <threading/condvar.h>
+#include <threading/rwlock.h>
+#include <threading/spinlock.h>
+#include <collections/hashtable.h>
+#include <collections/linked_list.h>
+#include <processing/jobs/callback_job.h>
+
+#ifndef HAVE_STRUCT_SOCKADDR_SA_LEN
+#error Cannot compile this plugin on systems where 'struct sockaddr' has no sa_len member.
+#endif
+
+/** properly align sockaddrs */
+#ifdef __APPLE__
+/* Apple always uses 4 bytes */
+#define SA_ALIGN 4
+#else
+/* while on other platforms like FreeBSD it depends on the architecture */
+#define SA_ALIGN sizeof(long)
+#endif
+#define SA_LEN(len) ((len) > 0 ? (((len)+SA_ALIGN-1) & ~(SA_ALIGN-1)) : SA_ALIGN)
+
+/** delay before firing roam events (ms) */
+#define ROAM_DELAY 100
+
+/** delay before reinstalling routes (ms) */
+#define ROUTE_DELAY 100
+
+typedef struct addr_entry_t addr_entry_t;
+
+/**
+ * IP address in an inface_entry_t
+ */
+struct addr_entry_t {
+
+	/** The ip address */
+	host_t *ip;
+
+	/** virtual IP managed by us */
+	bool virtual;
+};
+
+/**
+ * destroy a addr_entry_t object
+ */
+static void addr_entry_destroy(addr_entry_t *this)
+{
+	this->ip->destroy(this->ip);
+	free(this);
+}
+
+typedef struct iface_entry_t iface_entry_t;
+
+/**
+ * A network interface on this system, containing addr_entry_t's
+ */
+struct iface_entry_t {
+
+	/** interface index */
+	int ifindex;
+
+	/** name of the interface */
+	char ifname[IFNAMSIZ];
+
+	/** interface flags, as in netdevice(7) SIOCGIFFLAGS */
+	u_int flags;
+
+	/** list of addresses as host_t */
+	linked_list_t *addrs;
+
+	/** TRUE if usable by config */
+	bool usable;
+};
+
+/**
+ * destroy an interface entry
+ */
+static void iface_entry_destroy(iface_entry_t *this)
+{
+	this->addrs->destroy_function(this->addrs, (void*)addr_entry_destroy);
+	free(this);
+}
+
+/**
+ * check if an interface is up
+ */
+static inline bool iface_entry_up(iface_entry_t *iface)
+{
+	return (iface->flags & IFF_UP) == IFF_UP;
+}
+
+/**
+ * check if an interface is up and usable
+ */
+static inline bool iface_entry_up_and_usable(iface_entry_t *iface)
+{
+	return iface->usable && iface_entry_up(iface);
+}
+
+typedef struct addr_map_entry_t addr_map_entry_t;
+
+/**
+ * Entry that maps an IP address to an interface entry
+ */
+struct addr_map_entry_t {
+	/** The IP address */
+	host_t *ip;
+
+	/** The address entry for this IP address */
+	addr_entry_t *addr;
+
+	/** The interface this address is installed on */
+	iface_entry_t *iface;
+};
+
+/**
+ * Hash a addr_map_entry_t object, all entries with the same IP address
+ * are stored in the same bucket
+ */
+static u_int addr_map_entry_hash(addr_map_entry_t *this)
+{
+	return chunk_hash(this->ip->get_address(this->ip));
+}
+
+/**
+ * Compare two addr_map_entry_t objects, two entries are equal if they are
+ * installed on the same interface
+ */
+static bool addr_map_entry_equals(addr_map_entry_t *a, addr_map_entry_t *b)
+{
+	return a->iface->ifindex == b->iface->ifindex &&
+		   a->ip->ip_equals(a->ip, b->ip);
+}
+
+/**
+ * Used with get_match this finds an address entry if it is installed on
+ * an up and usable interface
+ */
+static bool addr_map_entry_match_up_and_usable(addr_map_entry_t *a,
+											   addr_map_entry_t *b)
+{
+	return !b->addr->virtual && iface_entry_up_and_usable(b->iface) &&
+			a->ip->ip_equals(a->ip, b->ip);
+}
+
+/**
+ * Used with get_match this finds an address entry if it is installed as virtual
+ * IP address
+ */
+static bool addr_map_entry_match_virtual(addr_map_entry_t *a, addr_map_entry_t *b)
+{
+	return b->addr->virtual && a->ip->ip_equals(a->ip, b->ip);
+}
+
+/**
+ * Used with get_match this finds an address entry if it is installed on
+ * any active local interface
+ */
+static bool addr_map_entry_match_up(addr_map_entry_t *a, addr_map_entry_t *b)
+{
+	return !b->addr->virtual && iface_entry_up(b->iface) &&
+			a->ip->ip_equals(a->ip, b->ip);
+}
+
+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;
+
+	/** Gateway for this route */
+	host_t *gateway;
+
+	/** Destination net */
+	chunk_t dst_net;
+
+	/** Destination net prefixlen */
+	u_int8_t prefixlen;
+};
+
+/**
+ * Clone a route_entry_t object.
+ */
+static route_entry_t *route_entry_clone(route_entry_t *this)
+{
+	route_entry_t *route;
+
+	INIT(route,
+		.if_name = strdup(this->if_name),
+		.gateway = this->gateway ? this->gateway->clone(this->gateway) : NULL,
+		.dst_net = chunk_clone(this->dst_net),
+		.prefixlen = this->prefixlen,
+	);
+	return route;
+}
+
+/**
+ * Destroy a route_entry_t object
+ */
+static void route_entry_destroy(route_entry_t *this)
+{
+	free(this->if_name);
+	DESTROY_IF(this->gateway);
+	chunk_free(&this->dst_net);
+	free(this);
+}
+
+/**
+ * Hash a route_entry_t object
+ */
+static u_int route_entry_hash(route_entry_t *this)
+{
+	return chunk_hash_inc(chunk_from_thing(this->prefixlen),
+						  chunk_hash(this->dst_net));
+}
+
+/**
+ * Compare two route_entry_t objects
+ */
+static bool route_entry_equals(route_entry_t *a, route_entry_t *b)
+{
+	if (a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
+		chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen)
+	{
+		return (!a->gateway && !b->gateway) || (a->gateway && b->gateway &&
+					a->gateway->ip_equals(a->gateway, b->gateway));
+	}
+	return FALSE;
+}
+
+typedef struct net_change_t net_change_t;
+
+/**
+ * Queued network changes
+ */
+struct net_change_t {
+	/** Name of the interface that got activated (or an IP appeared on) */
+	char *if_name;
+};
+
+/**
+ * Destroy a net_change_t object
+ */
+static void net_change_destroy(net_change_t *this)
+{
+	free(this->if_name);
+	free(this);
+}
+
+/**
+ * Hash a net_change_t object
+ */
+static u_int net_change_hash(net_change_t *this)
+{
+	return chunk_hash(chunk_create(this->if_name, strlen(this->if_name)));
+}
+
+/**
+ * Compare two net_change_t objects
+ */
+static bool net_change_equals(net_change_t *a, net_change_t *b)
+{
+	return streq(a->if_name, b->if_name);
+}
+
+typedef struct private_kernel_pfroute_net_t private_kernel_pfroute_net_t;
+
+/**
+ * Private variables and functions of kernel_pfroute class.
+ */
+struct private_kernel_pfroute_net_t
+{
+	/**
+	 * Public part of the kernel_pfroute_t object.
+	 */
+	kernel_pfroute_net_t public;
+
+	/**
+	 * lock to access lists and maps
+	 */
+	rwlock_t *lock;
+
+	/**
+	 * Cached list of interfaces and their addresses (iface_entry_t)
+	 */
+	linked_list_t *ifaces;
+
+	/**
+	 * Map for IP addresses to iface_entry_t objects (addr_map_entry_t)
+	 */
+	hashtable_t *addrs;
+
+	/**
+	 * List of tun devices we installed for virtual IPs
+	 */
+	linked_list_t *tuns;
+
+	/**
+	 * mutex to communicate exclusively with PF_KEY
+	 */
+	mutex_t *mutex;
+
+	/**
+	 * condvar to signal if PF_KEY query got a response
+	 */
+	condvar_t *condvar;
+
+	/**
+	 * installed routes
+	 */
+	hashtable_t *routes;
+
+	/**
+	 * mutex for routes
+	 */
+	mutex_t *routes_lock;
+
+	/**
+	 * interface changes which may trigger route reinstallation
+	 */
+	hashtable_t *net_changes;
+
+	/**
+	 * mutex for route reinstallation triggers
+	 */
+	mutex_t *net_changes_lock;
+
+	/**
+	 * time of last route reinstallation
+	 */
+	timeval_t last_route_reinstall;
+
+	/**
+	 * pid to send PF_ROUTE messages with
+	 */
+	pid_t pid;
+
+	/**
+	 * PF_ROUTE socket to communicate with the kernel
+	 */
+	int socket;
+
+	/**
+	 * sequence number for messages sent to the kernel
+	 */
+	int seq;
+
+	/**
+	 * Sequence number a query is waiting for
+	 */
+	int waiting_seq;
+
+	/**
+	 * Allocated reply message from kernel
+	 */
+	struct rt_msghdr *reply;
+
+	/**
+	 * earliest time of the next roam event
+	 */
+	timeval_t next_roam;
+
+	/**
+	 * roam event due to address change
+	 */
+	bool roam_address;
+
+	/**
+	 * lock to check and update roam event time
+	 */
+	spinlock_t *roam_lock;
+
+	/**
+	 * Time in ms to wait for IP addresses to appear/disappear
+	 */
+	int vip_wait;
+
+	/**
+	 * whether to actually install virtual IPs
+	 */
+	bool install_virtual_ip;
+};
+
+
+/**
+ * Forward declaration
+ */
+static status_t manage_route(private_kernel_pfroute_net_t *this, int op,
+							 chunk_t dst_net, u_int8_t prefixlen,
+							 host_t *gateway, char *if_name);
+
+/**
+ * Clear the queued network changes.
+ */
+static void net_changes_clear(private_kernel_pfroute_net_t *this)
+{
+	enumerator_t *enumerator;
+	net_change_t *change;
+
+	enumerator = this->net_changes->create_enumerator(this->net_changes);
+	while (enumerator->enumerate(enumerator, NULL, (void**)&change))
+	{
+		this->net_changes->remove_at(this->net_changes, enumerator);
+		net_change_destroy(change);
+	}
+	enumerator->destroy(enumerator);
+}
+
+/**
+ * Act upon queued network changes.
+ */
+static job_requeue_t reinstall_routes(private_kernel_pfroute_net_t *this)
+{
+	enumerator_t *enumerator;
+	route_entry_t *route;
+
+	this->net_changes_lock->lock(this->net_changes_lock);
+	this->routes_lock->lock(this->routes_lock);
+
+	enumerator = this->routes->create_enumerator(this->routes);
+	while (enumerator->enumerate(enumerator, NULL, (void**)&route))
+	{
+		net_change_t *change, lookup = {
+			.if_name = route->if_name,
+		};
+		/* check if a change for the outgoing interface is queued */
+		change = this->net_changes->get(this->net_changes, &lookup);
+		if (change)
+		{
+			manage_route(this, RTM_ADD, route->dst_net, route->prefixlen,
+						 route->gateway, route->if_name);
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->routes_lock->unlock(this->routes_lock);
+
+	net_changes_clear(this);
+	this->net_changes_lock->unlock(this->net_changes_lock);
+	return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Queue route reinstallation caused by network changes for a given interface.
+ *
+ * The route reinstallation is delayed for a while and only done once for
+ * several calls during this delay, in order to avoid doing it too often.
+ * The interface name is freed.
+ */
+static void queue_route_reinstall(private_kernel_pfroute_net_t *this,
+								  char *if_name)
+{
+	net_change_t *update, *found;
+	timeval_t now;
+	job_t *job;
+
+	INIT(update,
+		.if_name = if_name
+	);
+
+	this->net_changes_lock->lock(this->net_changes_lock);
+	found = this->net_changes->put(this->net_changes, update, update);
+	if (found)
+	{
+		net_change_destroy(found);
+	}
+	time_monotonic(&now);
+	if (timercmp(&now, &this->last_route_reinstall, >))
+	{
+		timeval_add_ms(&now, ROUTE_DELAY);
+		this->last_route_reinstall = now;
+
+		job = (job_t*)callback_job_create((callback_job_cb_t)reinstall_routes,
+										  this, NULL, NULL);
+		lib->scheduler->schedule_job_ms(lib->scheduler, job, ROUTE_DELAY);
+	}
+	this->net_changes_lock->unlock(this->net_changes_lock);
+}
+
+/**
+ * Add an address map entry
+ */
+static void addr_map_entry_add(private_kernel_pfroute_net_t *this,
+							   addr_entry_t *addr, iface_entry_t *iface)
+{
+	addr_map_entry_t *entry;
+
+	INIT(entry,
+		.ip = addr->ip,
+		.addr = addr,
+		.iface = iface,
+	);
+	entry = this->addrs->put(this->addrs, entry, entry);
+	free(entry);
+}
+
+/**
+ * Remove an address map entry (the argument order is a bit strange because
+ * it is also used with linked_list_t.invoke_function)
+ */
+static void addr_map_entry_remove(addr_entry_t *addr, iface_entry_t *iface,
+								  private_kernel_pfroute_net_t *this)
+{
+	addr_map_entry_t *entry, lookup = {
+		.ip = addr->ip,
+		.addr = addr,
+		.iface = iface,
+	};
+
+	entry = this->addrs->remove(this->addrs, &lookup);
+	free(entry);
+}
+
+/**
+ * callback function that raises the delayed roam event
+ */
+static job_requeue_t roam_event(private_kernel_pfroute_net_t *this)
+{
+	bool address;
+
+	this->roam_lock->lock(this->roam_lock);
+	address = this->roam_address;
+	this->roam_address = FALSE;
+	this->roam_lock->unlock(this->roam_lock);
+	charon->kernel->roam(charon->kernel, address);
+	return JOB_REQUEUE_NONE;
+}
+
+/**
+ * fire a roaming event. we delay it for a bit and fire only one event
+ * for multiple calls. otherwise we would create too many events.
+ */
+static void fire_roam_event(private_kernel_pfroute_net_t *this, bool address)
+{
+	timeval_t now;
+	job_t *job;
+
+	time_monotonic(&now);
+	this->roam_lock->lock(this->roam_lock);
+	this->roam_address |= address;
+	if (!timercmp(&now, &this->next_roam, >))
+	{
+		this->roam_lock->unlock(this->roam_lock);
+		return;
+	}
+	timeval_add_ms(&now, ROAM_DELAY);
+	this->next_roam = now;
+	this->roam_lock->unlock(this->roam_lock);
+
+	job = (job_t*)callback_job_create((callback_job_cb_t)roam_event,
+									  this, NULL, NULL);
+	lib->scheduler->schedule_job_ms(lib->scheduler, job, ROAM_DELAY);
+}
+
+/**
+ * Data for enumerator over rtmsg sockaddrs
+ */
+typedef struct {
+	/** implements enumerator */
+	enumerator_t public;
+	/** copy of attribute bitfield */
+	int types;
+	/** bytes remaining in buffer */
+	int remaining;
+	/** next sockaddr to enumerate */
+	struct sockaddr *addr;
+} rt_enumerator_t;
+
+METHOD(enumerator_t, rt_enumerate, bool,
+	rt_enumerator_t *this, int *xtype, struct sockaddr **addr)
+{
+	int i, type;
+
+	if (this->remaining < sizeof(this->addr->sa_len) ||
+		this->remaining < this->addr->sa_len)
+	{
+		return FALSE;
+	}
+	for (i = 0; i < RTAX_MAX; i++)
+	{
+		type = (1 << i);
+		if (this->types & type)
+		{
+			this->types &= ~type;
+			*addr = this->addr;
+			*xtype = i;
+			this->remaining -= SA_LEN(this->addr->sa_len);
+			this->addr = (struct sockaddr*)((char*)this->addr +
+											SA_LEN(this->addr->sa_len));
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/**
+ * Create an enumerator over sockaddrs in rt/if messages
+ */
+static enumerator_t *create_rt_enumerator(int types, int remaining,
+										  struct sockaddr *addr)
+{
+	rt_enumerator_t *this;
+
+	INIT(this,
+		.public = {
+			.enumerate = (void*)_rt_enumerate,
+			.destroy = (void*)free,
+		},
+		.types = types,
+		.remaining = remaining,
+		.addr = addr,
+	);
+	return &this->public;
+}
+
+/**
+ * Create a safe enumerator over sockaddrs in rt_msghdr
+ */
+static enumerator_t *create_rtmsg_enumerator(struct rt_msghdr *hdr)
+{
+	return create_rt_enumerator(hdr->rtm_addrs, hdr->rtm_msglen - sizeof(*hdr),
+								(struct sockaddr *)(hdr + 1));
+}
+
+/**
+ * Create a safe enumerator over sockaddrs in ifa_msghdr
+ */
+static enumerator_t *create_ifamsg_enumerator(struct ifa_msghdr *hdr)
+{
+	return create_rt_enumerator(hdr->ifam_addrs, hdr->ifam_msglen - sizeof(*hdr),
+								(struct sockaddr *)(hdr + 1));
+}
+
+/**
+ * Process an RTM_*ADDR message from the kernel
+ */
+static void process_addr(private_kernel_pfroute_net_t *this,
+						 struct ifa_msghdr *ifa)
+{
+	struct sockaddr *sockaddr;
+	host_t *host = NULL;
+	enumerator_t *ifaces, *addrs;
+	iface_entry_t *iface;
+	addr_entry_t *addr;
+	bool found = FALSE, changed = FALSE, roam = FALSE;
+	enumerator_t *enumerator;
+	char *ifname = NULL;
+	int type;
+
+	enumerator = create_ifamsg_enumerator(ifa);
+	while (enumerator->enumerate(enumerator, &type, &sockaddr))
+	{
+		if (type == RTAX_IFA)
+		{
+			host = host_create_from_sockaddr(sockaddr);
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	if (!host || host->is_anyaddr(host))
+	{
+		DESTROY_IF(host);
+		return;
+	}
+
+	this->lock->write_lock(this->lock);
+	ifaces = this->ifaces->create_enumerator(this->ifaces);
+	while (ifaces->enumerate(ifaces, &iface))
+	{
+		if (iface->ifindex == ifa->ifam_index)
+		{
+			addrs = iface->addrs->create_enumerator(iface->addrs);
+			while (addrs->enumerate(addrs, &addr))
+			{
+				if (host->ip_equals(host, addr->ip))
+				{
+					found = TRUE;
+					if (ifa->ifam_type == RTM_DELADDR)
+					{
+						iface->addrs->remove_at(iface->addrs, addrs);
+						if (!addr->virtual && iface->usable)
+						{
+							changed = TRUE;
+							DBG1(DBG_KNL, "%H disappeared from %s",
+								 host, iface->ifname);
+						}
+						addr_map_entry_remove(addr, iface, this);
+						addr_entry_destroy(addr);
+					}
+				}
+			}
+			addrs->destroy(addrs);
+
+			if (!found && ifa->ifam_type == RTM_NEWADDR)
+			{
+				INIT(addr,
+					.ip = host->clone(host),
+				);
+				changed = TRUE;
+				ifname = strdup(iface->ifname);
+				iface->addrs->insert_last(iface->addrs, addr);
+				addr_map_entry_add(this, addr, iface);
+				if (iface->usable)
+				{
+					DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
+				}
+			}
+
+			if (changed && iface_entry_up_and_usable(iface))
+			{
+				roam = TRUE;
+			}
+			break;
+		}
+	}
+	ifaces->destroy(ifaces);
+	this->lock->unlock(this->lock);
+	host->destroy(host);
+
+	if (roam && ifname)
+	{
+		queue_route_reinstall(this, ifname);
+	}
+	else
+	{
+		free(ifname);
+	}
+
+	if (roam)
+	{
+		fire_roam_event(this, TRUE);
+	}
+}
+
+/**
+ * Re-initialize address list of an interface if it changes state
+ */
+static void repopulate_iface(private_kernel_pfroute_net_t *this,
+							 iface_entry_t *iface)
+{
+	struct ifaddrs *ifap, *ifa;
+	addr_entry_t *addr;
+
+	while (iface->addrs->remove_last(iface->addrs, (void**)&addr) == SUCCESS)
+	{
+		addr_map_entry_remove(addr, iface, this);
+		addr_entry_destroy(addr);
+	}
+
+	if (getifaddrs(&ifap) == 0)
+	{
+		for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
+		{
+			if (ifa->ifa_addr && streq(ifa->ifa_name, iface->ifname))
+			{
+				switch (ifa->ifa_addr->sa_family)
+				{
+					case AF_INET:
+					case AF_INET6:
+						INIT(addr,
+							.ip = host_create_from_sockaddr(ifa->ifa_addr),
+						);
+						iface->addrs->insert_last(iface->addrs, addr);
+						addr_map_entry_add(this, addr, iface);
+						break;
+					default:
+						break;
+				}
+			}
+		}
+		freeifaddrs(ifap);
+	}
+}
+
+/**
+ * Process an RTM_IFINFO message from the kernel
+ */
+static void process_link(private_kernel_pfroute_net_t *this,
+						 struct if_msghdr *msg)
+{
+	enumerator_t *enumerator;
+	iface_entry_t *iface;
+	bool roam = FALSE, found = FALSE, update_routes = FALSE;
+
+	this->lock->write_lock(this->lock);
+	enumerator = this->ifaces->create_enumerator(this->ifaces);
+	while (enumerator->enumerate(enumerator, &iface))
+	{
+		if (iface->ifindex == msg->ifm_index)
+		{
+			if (iface->usable)
+			{
+				if (!(iface->flags & IFF_UP) && (msg->ifm_flags & IFF_UP))
+				{
+					roam = update_routes = TRUE;
+					DBG1(DBG_KNL, "interface %s activated", iface->ifname);
+				}
+				else if ((iface->flags & IFF_UP) && !(msg->ifm_flags & IFF_UP))
+				{
+					roam = TRUE;
+					DBG1(DBG_KNL, "interface %s deactivated", iface->ifname);
+				}
+			}
+#ifdef __APPLE__
+			/* There seems to be a race condition on 10.10, where we get
+			 * the RTM_IFINFO, but getifaddrs() does not return the virtual
+			 * IP installed on a tun device, but we also don't get a
+			 * RTM_NEWADDR. We therefore could miss the new address, letting
+			 * virtual IP installation fail. Delaying getifaddrs() helps,
+			 * but is obviously not a clean fix. */
+			usleep(50000);
+#endif
+			iface->flags = msg->ifm_flags;
+			repopulate_iface(this, iface);
+			found = TRUE;
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	if (!found)
+	{
+		INIT(iface,
+			.ifindex = msg->ifm_index,
+			.flags = msg->ifm_flags,
+			.addrs = linked_list_create(),
+		);
+		if (if_indextoname(iface->ifindex, iface->ifname))
+		{
+			DBG1(DBG_KNL, "interface %s appeared", iface->ifname);
+			iface->usable = charon->kernel->is_interface_usable(charon->kernel,
+																iface->ifname);
+			repopulate_iface(this, iface);
+			this->ifaces->insert_last(this->ifaces, iface);
+			if (iface->usable)
+			{
+				roam = update_routes = TRUE;
+			}
+		}
+		else
+		{
+			free(iface);
+		}
+	}
+	this->lock->unlock(this->lock);
+
+	if (update_routes)
+	{
+		queue_route_reinstall(this, strdup(iface->ifname));
+	}
+
+	if (roam)
+	{
+		fire_roam_event(this, TRUE);
+	}
+}
+
+#ifdef HAVE_RTM_IFANNOUNCE
+
+/**
+ * Process an RTM_IFANNOUNCE message from the kernel
+ */
+static void process_announce(private_kernel_pfroute_net_t *this,
+							 struct if_announcemsghdr *msg)
+{
+	enumerator_t *enumerator;
+	iface_entry_t *iface;
+
+	if (msg->ifan_what != IFAN_DEPARTURE)
+	{
+		/* we handle new interfaces in process_link() */
+		return;
+	}
+
+	this->lock->write_lock(this->lock);
+	enumerator = this->ifaces->create_enumerator(this->ifaces);
+	while (enumerator->enumerate(enumerator, &iface))
+	{
+		if (iface->ifindex == msg->ifan_index)
+		{
+			DBG1(DBG_KNL, "interface %s disappeared", iface->ifname);
+			this->ifaces->remove_at(this->ifaces, enumerator);
+			iface_entry_destroy(iface);
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->lock->unlock(this->lock);
+}
+
+#endif /* HAVE_RTM_IFANNOUNCE */
+
+/**
+ * Process an RTM_*ROUTE message from the kernel
+ */
+static void process_route(private_kernel_pfroute_net_t *this,
+						  struct rt_msghdr *msg)
+{
+
+}
+
+/**
+ * Receives PF_ROUTE messages from kernel
+ */
+static bool receive_events(private_kernel_pfroute_net_t *this, int fd,
+						   watcher_event_t event)
+{
+	struct {
+		union {
+			struct rt_msghdr rtm;
+			struct if_msghdr ifm;
+			struct ifa_msghdr ifam;
+#ifdef HAVE_RTM_IFANNOUNCE
+			struct if_announcemsghdr ifanm;
+#endif
+		};
+		char buf[sizeof(struct sockaddr_storage) * RTAX_MAX];
+	} msg;
+	int len, hdrlen;
+
+	len = recv(this->socket, &msg, sizeof(msg), MSG_DONTWAIT);
+	if (len < 0)
+	{
+		switch (errno)
+		{
+			case EINTR:
+			case EAGAIN:
+				return TRUE;
+			default:
+				DBG1(DBG_KNL, "unable to receive from PF_ROUTE event socket");
+				sleep(1);
+				return TRUE;
+		}
+	}
+
+	if (len < offsetof(struct rt_msghdr, rtm_flags) || len < msg.rtm.rtm_msglen)
+	{
+		DBG1(DBG_KNL, "received invalid PF_ROUTE message");
+		return TRUE;
+	}
+	if (msg.rtm.rtm_version != RTM_VERSION)
+	{
+		DBG1(DBG_KNL, "received PF_ROUTE message with unsupported version: %d",
+			 msg.rtm.rtm_version);
+		return TRUE;
+	}
+	switch (msg.rtm.rtm_type)
+	{
+		case RTM_NEWADDR:
+		case RTM_DELADDR:
+			hdrlen = sizeof(msg.ifam);
+			break;
+		case RTM_IFINFO:
+			hdrlen = sizeof(msg.ifm);
+			break;
+#ifdef HAVE_RTM_IFANNOUNCE
+		case RTM_IFANNOUNCE:
+			hdrlen = sizeof(msg.ifanm);
+			break;
+#endif /* HAVE_RTM_IFANNOUNCE */
+		case RTM_ADD:
+		case RTM_DELETE:
+		case RTM_GET:
+			hdrlen = sizeof(msg.rtm);
+			break;
+		default:
+			return TRUE;
+	}
+	if (msg.rtm.rtm_msglen < hdrlen)
+	{
+		DBG1(DBG_KNL, "ignoring short PF_ROUTE message");
+		return TRUE;
+	}
+	switch (msg.rtm.rtm_type)
+	{
+		case RTM_NEWADDR:
+		case RTM_DELADDR:
+			process_addr(this, &msg.ifam);
+			break;
+		case RTM_IFINFO:
+			process_link(this, &msg.ifm);
+			break;
+#ifdef HAVE_RTM_IFANNOUNCE
+		case RTM_IFANNOUNCE:
+			process_announce(this, &msg.ifanm);
+			break;
+#endif /* HAVE_RTM_IFANNOUNCE */
+		case RTM_ADD:
+		case RTM_DELETE:
+			process_route(this, &msg.rtm);
+			break;
+		default:
+			break;
+	}
+
+	this->mutex->lock(this->mutex);
+	if (msg.rtm.rtm_pid == this->pid && msg.rtm.rtm_seq == this->waiting_seq)
+	{
+		/* seems like the message someone is waiting for, deliver */
+		this->reply = realloc(this->reply, msg.rtm.rtm_msglen);
+		memcpy(this->reply, &msg, msg.rtm.rtm_msglen);
+	}
+	/* signal on any event, add_ip()/del_ip() might wait for it */
+	this->condvar->broadcast(this->condvar);
+	this->mutex->unlock(this->mutex);
+
+	return TRUE;
+}
+
+
+/** enumerator over addresses */
+typedef struct {
+	private_kernel_pfroute_net_t* this;
+	/** which addresses to enumerate */
+	kernel_address_type_t which;
+} address_enumerator_t;
+
+/**
+ * cleanup function for address enumerator
+ */
+static void address_enumerator_destroy(address_enumerator_t *data)
+{
+	data->this->lock->unlock(data->this->lock);
+	free(data);
+}
+
+/**
+ * filter for addresses
+ */
+static bool filter_addresses(address_enumerator_t *data,
+							 addr_entry_t** in, host_t** out)
+{
+	host_t *ip;
+	if (!(data->which & ADDR_TYPE_VIRTUAL) && (*in)->virtual)
+	{   /* skip virtual interfaces added by us */
+		return FALSE;
+	}
+	if (!(data->which & ADDR_TYPE_REGULAR) && !(*in)->virtual)
+	{	/* address is regular, but not requested */
+		return FALSE;
+	}
+	ip = (*in)->ip;
+	if (ip->get_family(ip) == AF_INET6)
+	{
+		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ip->get_sockaddr(ip);
+		if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
+		{   /* skip addresses with a unusable scope */
+			return FALSE;
+		}
+	}
+	*out = ip;
+	return TRUE;
+}
+
+/**
+ * enumerator constructor for interfaces
+ */
+static enumerator_t *create_iface_enumerator(iface_entry_t *iface,
+											 address_enumerator_t *data)
+{
+	return enumerator_create_filter(iface->addrs->create_enumerator(iface->addrs),
+									(void*)filter_addresses, data, NULL);
+}
+
+/**
+ * filter for interfaces
+ */
+static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in,
+							  iface_entry_t** out)
+{
+	if (!(data->which & ADDR_TYPE_IGNORED) && !(*in)->usable)
+	{	/* skip interfaces excluded by config */
+		return FALSE;
+	}
+	if (!(data->which & ADDR_TYPE_LOOPBACK) && ((*in)->flags & IFF_LOOPBACK))
+	{	/* ignore loopback devices */
+		return FALSE;
+	}
+	if (!(data->which & ADDR_TYPE_DOWN) && !((*in)->flags & IFF_UP))
+	{	/* skip interfaces not up */
+		return FALSE;
+	}
+	*out = *in;
+	return TRUE;
+}
+
+METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
+	private_kernel_pfroute_net_t *this, kernel_address_type_t which)
+{
+	address_enumerator_t *data;
+
+	INIT(data,
+		.this = this,
+		.which = which,
+	);
+
+	this->lock->read_lock(this->lock);
+	return enumerator_create_nested(
+				enumerator_create_filter(
+					this->ifaces->create_enumerator(this->ifaces),
+					(void*)filter_interfaces, data, NULL),
+				(void*)create_iface_enumerator, data,
+				(void*)address_enumerator_destroy);
+}
+
+METHOD(kernel_net_t, get_features, kernel_feature_t,
+	private_kernel_pfroute_net_t *this)
+{
+	return KERNEL_REQUIRE_EXCLUDE_ROUTE;
+}
+
+METHOD(kernel_net_t, get_interface_name, bool,
+	private_kernel_pfroute_net_t *this, host_t* ip, char **name)
+{
+	addr_map_entry_t *entry, lookup = {
+		.ip = ip,
+	};
+
+	if (ip->is_anyaddr(ip))
+	{
+		return FALSE;
+	}
+	this->lock->read_lock(this->lock);
+	/* first try to find it on an up and usable interface */
+	entry = this->addrs->get_match(this->addrs, &lookup,
+								  (void*)addr_map_entry_match_up_and_usable);
+	if (entry)
+	{
+		if (name)
+		{
+			*name = strdup(entry->iface->ifname);
+			DBG2(DBG_KNL, "%H is on interface %s", ip, *name);
+		}
+		this->lock->unlock(this->lock);
+		return TRUE;
+	}
+	/* check if it is a virtual IP */
+	entry = this->addrs->get_match(this->addrs, &lookup,
+								  (void*)addr_map_entry_match_virtual);
+	if (entry)
+	{
+		if (name)
+		{
+			*name = strdup(entry->iface->ifname);
+			DBG2(DBG_KNL, "virtual IP %H is on interface %s", ip, *name);
+		}
+		this->lock->unlock(this->lock);
+		return TRUE;
+	}
+	/* maybe it is installed on an ignored interface */
+	entry = this->addrs->get_match(this->addrs, &lookup,
+								  (void*)addr_map_entry_match_up);
+	if (!entry)
+	{	/* the address does not exist, is on a down interface */
+		DBG2(DBG_KNL, "%H is not a local address or the interface is down", ip);
+	}
+	this->lock->unlock(this->lock);
+	return FALSE;
+}
+
+METHOD(kernel_net_t, add_ip, status_t,
+	private_kernel_pfroute_net_t *this, host_t *vip, int prefix,
+	char *ifname)
+{
+	enumerator_t *ifaces, *addrs;
+	iface_entry_t *iface;
+	addr_entry_t *addr;
+	tun_device_t *tun;
+	bool timeout = FALSE;
+
+	if (!this->install_virtual_ip)
+	{	/* disabled by config */
+		return SUCCESS;
+	}
+
+	tun = tun_device_create(NULL);
+	if (!tun)
+	{
+		return FAILED;
+	}
+	if (prefix == -1)
+	{
+		prefix = vip->get_address(vip).len * 8;
+	}
+	if (!tun->up(tun) || !tun->set_address(tun, vip, prefix))
+	{
+		tun->destroy(tun);
+		return FAILED;
+	}
+
+	/* wait until address appears */
+	this->mutex->lock(this->mutex);
+	while (!timeout && !get_interface_name(this, vip, NULL))
+	{
+		timeout = this->condvar->timed_wait(this->condvar, this->mutex,
+											this->vip_wait);
+	}
+	this->mutex->unlock(this->mutex);
+	if (timeout)
+	{
+		DBG1(DBG_KNL, "virtual IP %H did not appear on %s",
+			 vip, tun->get_name(tun));
+		tun->destroy(tun);
+		return FAILED;
+	}
+
+	this->lock->write_lock(this->lock);
+	this->tuns->insert_last(this->tuns, tun);
+
+	ifaces = this->ifaces->create_enumerator(this->ifaces);
+	while (ifaces->enumerate(ifaces, &iface))
+	{
+		if (streq(iface->ifname, tun->get_name(tun)))
+		{
+			addrs = iface->addrs->create_enumerator(iface->addrs);
+			while (addrs->enumerate(addrs, &addr))
+			{
+				if (addr->ip->ip_equals(addr->ip, vip))
+				{
+					addr->virtual = TRUE;
+				}
+			}
+			addrs->destroy(addrs);
+			/* during IKEv1 reauthentication, children get moved from
+			 * old the new SA before the virtual IP is available. This
+			 * kills the route for our virtual IP, reinstall. */
+			queue_route_reinstall(this, strdup(iface->ifname));
+			break;
+		}
+	}
+	ifaces->destroy(ifaces);
+	/* lets do this while holding the lock, thus preventing another thread
+	 * from deleting the TUN device concurrently, hopefully listeners are quick
+	 * and cause no deadlocks */
+	charon->kernel->tun(charon->kernel, tun, TRUE);
+	this->lock->unlock(this->lock);
+
+	return SUCCESS;
+}
+
+METHOD(kernel_net_t, del_ip, status_t,
+	private_kernel_pfroute_net_t *this, host_t *vip, int prefix,
+	bool wait)
+{
+	enumerator_t *enumerator;
+	tun_device_t *tun;
+	host_t *addr;
+	bool timeout = FALSE, found = FALSE;
+
+	if (!this->install_virtual_ip)
+	{	/* disabled by config */
+		return SUCCESS;
+	}
+
+	this->lock->write_lock(this->lock);
+	enumerator = this->tuns->create_enumerator(this->tuns);
+	while (enumerator->enumerate(enumerator, &tun))
+	{
+		addr = tun->get_address(tun, NULL);
+		if (addr && addr->ip_equals(addr, vip))
+		{
+			this->tuns->remove_at(this->tuns, enumerator);
+			charon->kernel->tun(charon->kernel, tun, FALSE);
+			tun->destroy(tun);
+			found = TRUE;
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->lock->unlock(this->lock);
+
+	if (!found)
+	{
+		return NOT_FOUND;
+	}
+	/* wait until address disappears */
+	if (wait)
+	{
+		this->mutex->lock(this->mutex);
+		while (!timeout && get_interface_name(this, vip, NULL))
+		{
+			timeout = this->condvar->timed_wait(this->condvar, this->mutex,
+												this->vip_wait);
+		}
+		this->mutex->unlock(this->mutex);
+		if (timeout)
+		{
+			DBG1(DBG_KNL, "virtual IP %H did not disappear from tun", vip);
+			return FAILED;
+		}
+	}
+	return SUCCESS;
+}
+
+/**
+ * Append a sockaddr_in/in6 of given type to routing message
+ */
+static void add_rt_addr(struct rt_msghdr *hdr, int type, host_t *addr)
+{
+	if (addr)
+	{
+		int len;
+
+		len = *addr->get_sockaddr_len(addr);
+		memcpy((char*)hdr + hdr->rtm_msglen, addr->get_sockaddr(addr), len);
+		hdr->rtm_msglen += SA_LEN(len);
+		hdr->rtm_addrs |= type;
+	}
+}
+
+/**
+ * Append a subnet mask sockaddr using the given prefix to routing message
+ */
+static void add_rt_mask(struct rt_msghdr *hdr, int type, int family, int prefix)
+{
+	host_t *mask;
+
+	mask = host_create_netmask(family, prefix);
+	if (mask)
+	{
+		add_rt_addr(hdr, type, mask);
+		mask->destroy(mask);
+	}
+}
+
+/**
+ * Append an interface name sockaddr_dl to routing message
+ */
+static void add_rt_ifname(struct rt_msghdr *hdr, int type, char *name)
+{
+	struct sockaddr_dl sdl = {
+		.sdl_len = sizeof(struct sockaddr_dl),
+		.sdl_family = AF_LINK,
+		.sdl_nlen = strlen(name),
+	};
+
+	if (strlen(name) <= sizeof(sdl.sdl_data))
+	{
+		memcpy(sdl.sdl_data, name, sdl.sdl_nlen);
+		memcpy((char*)hdr + hdr->rtm_msglen, &sdl, sdl.sdl_len);
+		hdr->rtm_msglen += SA_LEN(sdl.sdl_len);
+		hdr->rtm_addrs |= type;
+	}
+}
+
+/**
+ * Add or remove a route
+ */
+static status_t manage_route(private_kernel_pfroute_net_t *this, int op,
+							 chunk_t dst_net, u_int8_t prefixlen,
+							 host_t *gateway, char *if_name)
+{
+	struct {
+		struct rt_msghdr hdr;
+		char buf[sizeof(struct sockaddr_storage) * RTAX_MAX];
+	} msg = {
+		.hdr = {
+			.rtm_version = RTM_VERSION,
+			.rtm_type = op,
+			.rtm_flags = RTF_UP | RTF_STATIC,
+			.rtm_pid = this->pid,
+			.rtm_seq = ref_get(&this->seq),
+		},
+	};
+	host_t *dst;
+	int type;
+
+	if (prefixlen == 0 && dst_net.len)
+	{
+		status_t status;
+		chunk_t half;
+
+		half = chunk_clonea(dst_net);
+		half.ptr[0] |= 0x80;
+		prefixlen = 1;
+		status = manage_route(this, op, half, prefixlen, gateway, if_name);
+		if (status != SUCCESS)
+		{
+			return status;
+		}
+	}
+
+	dst = host_create_from_chunk(AF_UNSPEC, dst_net, 0);
+	if (!dst)
+	{
+		return FAILED;
+	}
+
+	if ((dst->get_family(dst) == AF_INET && prefixlen == 32) ||
+		(dst->get_family(dst) == AF_INET6 && prefixlen == 128))
+	{
+		msg.hdr.rtm_flags |= RTF_HOST | RTF_GATEWAY;
+	}
+
+	msg.hdr.rtm_msglen = sizeof(struct rt_msghdr);
+	for (type = 0; type < RTAX_MAX; type++)
+	{
+		switch (type)
+		{
+			case RTAX_DST:
+				add_rt_addr(&msg.hdr, RTA_DST, dst);
+				break;
+			case RTAX_NETMASK:
+				if (!(msg.hdr.rtm_flags & RTF_HOST))
+				{
+					add_rt_mask(&msg.hdr, RTA_NETMASK,
+								dst->get_family(dst), prefixlen);
+				}
+				break;
+			case RTAX_IFP:
+				if (if_name)
+				{
+					add_rt_ifname(&msg.hdr, RTA_IFP, if_name);
+				}
+				break;
+			case RTAX_GATEWAY:
+				if (gateway)
+				{
+					add_rt_addr(&msg.hdr, RTA_GATEWAY, gateway);
+				}
+				break;
+			default:
+				break;
+		}
+	}
+	dst->destroy(dst);
+
+	if (send(this->socket, &msg, msg.hdr.rtm_msglen, 0) != msg.hdr.rtm_msglen)
+	{
+		if (errno == EEXIST)
+		{
+			return ALREADY_DONE;
+		}
+		DBG1(DBG_KNL, "%s PF_ROUTE route failed: %s",
+			 op == RTM_ADD ? "adding" : "deleting", strerror(errno));
+		return FAILED;
+	}
+	return SUCCESS;
+}
+
+METHOD(kernel_net_t, add_route, status_t,
+	private_kernel_pfroute_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
+	host_t *gateway, host_t *src_ip, char *if_name)
+{
+	status_t status;
+	route_entry_t *found, route = {
+		.dst_net = dst_net,
+		.prefixlen = prefixlen,
+		.gateway = gateway,
+		.if_name = if_name,
+	};
+
+	this->routes_lock->lock(this->routes_lock);
+	found = this->routes->get(this->routes, &route);
+	if (found)
+	{
+		this->routes_lock->unlock(this->routes_lock);
+		return ALREADY_DONE;
+	}
+	status = manage_route(this, RTM_ADD, dst_net, prefixlen, gateway, if_name);
+	if (status == SUCCESS)
+	{
+		found = route_entry_clone(&route);
+		this->routes->put(this->routes, found, found);
+	}
+	this->routes_lock->unlock(this->routes_lock);
+	return status;
+}
+
+METHOD(kernel_net_t, del_route, status_t,
+	private_kernel_pfroute_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
+	host_t *gateway, host_t *src_ip, char *if_name)
+{
+	status_t status;
+	route_entry_t *found, route = {
+		.dst_net = dst_net,
+		.prefixlen = prefixlen,
+		.gateway = gateway,
+		.if_name = if_name,
+	};
+
+	this->routes_lock->lock(this->routes_lock);
+	found = this->routes->get(this->routes, &route);
+	if (!found)
+	{
+		this->routes_lock->unlock(this->routes_lock);
+		return NOT_FOUND;
+	}
+	this->routes->remove(this->routes, found);
+	route_entry_destroy(found);
+	status = manage_route(this, RTM_DELETE, dst_net, prefixlen, gateway,
+						  if_name);
+	this->routes_lock->unlock(this->routes_lock);
+	return status;
+}
+
+/**
+ * Do a route lookup for dest and return either the nexthop or the source
+ * address.
+ */
+static host_t *get_route(private_kernel_pfroute_net_t *this, bool nexthop,
+						 host_t *dest, host_t *src)
+{
+	struct {
+		struct rt_msghdr hdr;
+		char buf[sizeof(struct sockaddr_storage) * RTAX_MAX];
+	} msg = {
+		.hdr = {
+			.rtm_version = RTM_VERSION,
+			.rtm_type = RTM_GET,
+			.rtm_pid = this->pid,
+			.rtm_seq = ref_get(&this->seq),
+		},
+	};
+	host_t *host = NULL;
+	enumerator_t *enumerator;
+	struct sockaddr *addr;
+	bool failed = FALSE;
+	int type;
+
+retry:
+	msg.hdr.rtm_msglen = sizeof(struct rt_msghdr);
+	for (type = 0; type < RTAX_MAX; type++)
+	{
+		switch (type)
+		{
+			case RTAX_DST:
+				add_rt_addr(&msg.hdr, RTA_DST, dest);
+				break;
+			case RTAX_IFA:
+				add_rt_addr(&msg.hdr, RTA_IFA, src);
+				break;
+			case RTAX_IFP:
+				if (!nexthop)
+				{	/* add an empty IFP to ensure we get a source address */
+					add_rt_ifname(&msg.hdr, RTA_IFP, "");
+				}
+				break;
+			default:
+				break;
+		}
+	}
+	this->mutex->lock(this->mutex);
+
+	while (this->waiting_seq)
+	{
+		this->condvar->wait(this->condvar, this->mutex);
+	}
+	this->waiting_seq = msg.hdr.rtm_seq;
+	if (send(this->socket, &msg, msg.hdr.rtm_msglen, 0) == msg.hdr.rtm_msglen)
+	{
+		while (TRUE)
+		{
+			if (this->condvar->timed_wait(this->condvar, this->mutex, 1000))
+			{	/* timed out? */
+				break;
+			}
+			if (!this->reply)
+			{
+				continue;
+			}
+			enumerator = create_rtmsg_enumerator(this->reply);
+			while (enumerator->enumerate(enumerator, &type, &addr))
+			{
+				if (nexthop)
+				{
+					if (type == RTAX_DST && this->reply->rtm_flags & RTF_HOST)
+					{	/* probably a cloned/cached direct route, only use that
+						 * as fallback if no gateway is found */
+						host = host ?: host_create_from_sockaddr(addr);
+					}
+					if (type == RTAX_GATEWAY)
+					{	/* could actually be a MAC address */
+						host_t *gtw = host_create_from_sockaddr(addr);
+						if (gtw)
+						{
+							DESTROY_IF(host);
+							host = gtw;
+						}
+					}
+				}
+				else
+				{
+					if (type == RTAX_IFA)
+					{
+						host = host_create_from_sockaddr(addr);
+					}
+				}
+			}
+			enumerator->destroy(enumerator);
+			break;
+		}
+	}
+	else
+	{
+		failed = TRUE;
+	}
+	free(this->reply);
+	this->reply = NULL;
+	/* signal completion of query to a waiting thread */
+	this->waiting_seq = 0;
+	this->condvar->signal(this->condvar);
+	this->mutex->unlock(this->mutex);
+
+	if (failed)
+	{
+		if (src)
+		{	/* the given source address might be gone, try again without */
+			src = NULL;
+			msg.hdr.rtm_seq = ref_get(&this->seq);
+			msg.hdr.rtm_addrs = 0;
+			memset(msg.buf, 0, sizeof(msg.buf));
+			goto retry;
+		}
+		DBG1(DBG_KNL, "PF_ROUTE lookup failed: %s", strerror(errno));
+	}
+	if (nexthop)
+	{
+		host = host ?: dest->clone(dest);
+	}
+	else
+	{	/* make sure the source address is not virtual and usable */
+		addr_entry_t *entry, lookup = {
+			.ip = host,
+		};
+
+		if (!host)
+		{
+			return NULL;
+		}
+		this->lock->read_lock(this->lock);
+		entry = this->addrs->get_match(this->addrs, &lookup,
+									(void*)addr_map_entry_match_up_and_usable);
+		this->lock->unlock(this->lock);
+		if (!entry)
+		{
+			host->destroy(host);
+			return NULL;
+		}
+	}
+	DBG2(DBG_KNL, "using %H as %s to reach %H", host,
+		 nexthop ? "nexthop" : "address", dest);
+	return host;
+}
+
+METHOD(kernel_net_t, get_source_addr, host_t*,
+	private_kernel_pfroute_net_t *this, host_t *dest, host_t *src)
+{
+	return get_route(this, FALSE, dest, src);
+}
+
+METHOD(kernel_net_t, get_nexthop, host_t*,
+	private_kernel_pfroute_net_t *this, host_t *dest, int prefix, host_t *src)
+{
+	return get_route(this, TRUE, dest, src);
+}
+
+/**
+ * Initialize a list of local addresses.
+ */
+static status_t init_address_list(private_kernel_pfroute_net_t *this)
+{
+	struct ifaddrs *ifap, *ifa;
+	iface_entry_t *iface, *current;
+	addr_entry_t *addr;
+	enumerator_t *ifaces, *addrs;
+
+	DBG2(DBG_KNL, "known interfaces and IP addresses:");
+
+	if (getifaddrs(&ifap) < 0)
+	{
+		DBG1(DBG_KNL, "  failed to get interfaces!");
+		return FAILED;
+	}
+
+	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
+	{
+		if (ifa->ifa_addr == NULL)
+		{
+			continue;
+		}
+		switch(ifa->ifa_addr->sa_family)
+		{
+			case AF_LINK:
+			case AF_INET:
+			case AF_INET6:
+			{
+				iface = NULL;
+				ifaces = this->ifaces->create_enumerator(this->ifaces);
+				while (ifaces->enumerate(ifaces, &current))
+				{
+					if (streq(current->ifname, ifa->ifa_name))
+					{
+						iface = current;
+						break;
+					}
+				}
+				ifaces->destroy(ifaces);
+
+				if (!iface)
+				{
+					INIT(iface,
+						.ifindex = if_nametoindex(ifa->ifa_name),
+						.flags = ifa->ifa_flags,
+						.addrs = linked_list_create(),
+						.usable = charon->kernel->is_interface_usable(
+												charon->kernel, ifa->ifa_name),
+					);
+					memcpy(iface->ifname, ifa->ifa_name, IFNAMSIZ);
+					this->ifaces->insert_last(this->ifaces, iface);
+				}
+
+				if (ifa->ifa_addr->sa_family != AF_LINK)
+				{
+					INIT(addr,
+						.ip = host_create_from_sockaddr(ifa->ifa_addr),
+					);
+					iface->addrs->insert_last(iface->addrs, addr);
+					addr_map_entry_add(this, addr, iface);
+				}
+			}
+		}
+	}
+	freeifaddrs(ifap);
+
+	ifaces = this->ifaces->create_enumerator(this->ifaces);
+	while (ifaces->enumerate(ifaces, &iface))
+	{
+		if (iface->usable && iface->flags & IFF_UP)
+		{
+			DBG2(DBG_KNL, "  %s", iface->ifname);
+			addrs = iface->addrs->create_enumerator(iface->addrs);
+			while (addrs->enumerate(addrs, (void**)&addr))
+			{
+				DBG2(DBG_KNL, "    %H", addr->ip);
+			}
+			addrs->destroy(addrs);
+		}
+	}
+	ifaces->destroy(ifaces);
+
+	return SUCCESS;
+}
+
+METHOD(kernel_net_t, destroy, void,
+	private_kernel_pfroute_net_t *this)
+{
+	enumerator_t *enumerator;
+	route_entry_t *route;
+	addr_entry_t *addr;
+
+	enumerator = this->routes->create_enumerator(this->routes);
+	while (enumerator->enumerate(enumerator, NULL, (void**)&route))
+	{
+		manage_route(this, RTM_DELETE, route->dst_net, route->prefixlen,
+					 route->gateway, route->if_name);
+		route_entry_destroy(route);
+	}
+	enumerator->destroy(enumerator);
+	this->routes->destroy(this->routes);
+	this->routes_lock->destroy(this->routes_lock);
+
+	if (this->socket != -1)
+	{
+		lib->watcher->remove(lib->watcher, this->socket);
+		close(this->socket);
+	}
+
+	net_changes_clear(this);
+	this->net_changes->destroy(this->net_changes);
+	this->net_changes_lock->destroy(this->net_changes_lock);
+
+	enumerator = this->addrs->create_enumerator(this->addrs);
+	while (enumerator->enumerate(enumerator, NULL, (void**)&addr))
+	{
+		free(addr);
+	}
+	enumerator->destroy(enumerator);
+	this->addrs->destroy(this->addrs);
+	this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
+	this->tuns->destroy(this->tuns);
+	this->lock->destroy(this->lock);
+	this->mutex->destroy(this->mutex);
+	this->condvar->destroy(this->condvar);
+	this->roam_lock->destroy(this->roam_lock);
+	free(this->reply);
+	free(this);
+}
+
+/*
+ * Described in header.
+ */
+kernel_pfroute_net_t *kernel_pfroute_net_create()
+{
+	private_kernel_pfroute_net_t *this;
+
+	INIT(this,
+		.public = {
+			.interface = {
+				.get_features = _get_features,
+				.get_interface = _get_interface_name,
+				.create_address_enumerator = _create_address_enumerator,
+				.get_source_addr = _get_source_addr,
+				.get_nexthop = _get_nexthop,
+				.add_ip = _add_ip,
+				.del_ip = _del_ip,
+				.add_route = _add_route,
+				.del_route = _del_route,
+				.destroy = _destroy,
+			},
+		},
+		.pid = getpid(),
+		.ifaces = linked_list_create(),
+		.addrs = hashtable_create(
+								(hashtable_hash_t)addr_map_entry_hash,
+								(hashtable_equals_t)addr_map_entry_equals, 16),
+		.routes = hashtable_create((hashtable_hash_t)route_entry_hash,
+								   (hashtable_equals_t)route_entry_equals, 16),
+		.net_changes = hashtable_create(
+								   (hashtable_hash_t)net_change_hash,
+								   (hashtable_equals_t)net_change_equals, 16),
+		.tuns = linked_list_create(),
+		.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+		.condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
+		.routes_lock = mutex_create(MUTEX_TYPE_DEFAULT),
+		.net_changes_lock = mutex_create(MUTEX_TYPE_DEFAULT),
+		.roam_lock = spinlock_create(),
+		.vip_wait = lib->settings->get_int(lib->settings,
+						"%s.plugins.kernel-pfroute.vip_wait", 1000, lib->ns),
+		.install_virtual_ip = lib->settings->get_bool(lib->settings,
+						"%s.install_virtual_ip", TRUE, lib->ns),
+	);
+	timerclear(&this->last_route_reinstall);
+	timerclear(&this->next_roam);
+
+	/* create a PF_ROUTE socket to communicate with the kernel */
+	this->socket = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
+	if (this->socket == -1)
+	{
+		DBG1(DBG_KNL, "unable to create PF_ROUTE socket");
+		destroy(this);
+		return NULL;
+	}
+
+	if (streq(lib->ns, "starter"))
+	{
+		/* starter has no threads, so we do not register for kernel events */
+		if (shutdown(this->socket, SHUT_RD) != 0)
+		{
+			DBG1(DBG_KNL, "closing read end of PF_ROUTE socket failed: %s",
+				 strerror(errno));
+		}
+	}
+	else
+	{
+		lib->watcher->add(lib->watcher, this->socket, WATCHER_READ,
+						  (watcher_cb_t)receive_events, this);
+	}
+	if (init_address_list(this) != SUCCESS)
+	{
+		DBG1(DBG_KNL, "unable to get interface list");
+		destroy(this);
+		return NULL;
+	}
+
+	return &this->public;
+}
diff --git a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.h b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.h
similarity index 100%
rename from src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.h
rename to src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.h
diff --git a/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.c b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.c
new file mode 100644
index 0000000..acd834b
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+
+#include "kernel_pfroute_plugin.h"
+
+#include "kernel_pfroute_net.h"
+
+typedef struct private_kernel_pfroute_plugin_t private_kernel_pfroute_plugin_t;
+
+/**
+ * private data of kernel PF_ROUTE plugin
+ */
+struct private_kernel_pfroute_plugin_t {
+	/**
+	 * implements plugin interface
+	 */
+	kernel_pfroute_plugin_t public;
+};
+
+METHOD(plugin_t, get_name, char*,
+	private_kernel_pfroute_plugin_t *this)
+{
+	return "kernel-pfroute";
+}
+
+METHOD(plugin_t, get_features, int,
+	private_kernel_pfroute_plugin_t *this, plugin_feature_t *features[])
+{
+	static plugin_feature_t f[] = {
+		PLUGIN_CALLBACK(kernel_net_register, kernel_pfroute_net_create),
+			PLUGIN_PROVIDE(CUSTOM, "kernel-net"),
+	};
+	*features = f;
+	return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+	private_kernel_pfroute_plugin_t *this)
+{
+	free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *kernel_pfroute_plugin_create()
+{
+	private_kernel_pfroute_plugin_t *this;
+
+	INIT(this,
+		.public = {
+			.plugin = {
+				.get_name = _get_name,
+				.get_features = _get_features,
+				.destroy = _destroy,
+			},
+		},
+	);
+
+	return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.h b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.h
new file mode 100644
index 0000000..50642a5
--- /dev/null
+++ b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+/**
+ * @defgroup kernel_pfroute kernel_pfroute
+ * @ingroup cplugins
+ *
+ * @defgroup kernel_pfroute_plugin kernel_pfroute_plugin
+ * @{ @ingroup kernel_pfroute
+ */
+
+#ifndef KERNEL_PFROUTE_PLUGIN_H_
+#define KERNEL_PFROUTE_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct kernel_pfroute_plugin_t kernel_pfroute_plugin_t;
+
+/**
+ * PF_ROUTE kernel interface plugin
+ */
+struct kernel_pfroute_plugin_t {
+
+	/**
+	 * implements plugin interface
+	 */
+	plugin_t plugin;
+};
+
+#endif /** KERNEL_PFROUTE_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_wfp/Makefile.am b/src/libcharon/plugins/kernel_wfp/Makefile.am
index 85e5089..737a79b 100644
--- a/src/libcharon/plugins/kernel_wfp/Makefile.am
+++ b/src/libcharon/plugins/kernel_wfp/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/kernel_wfp/Makefile.in b/src/libcharon/plugins/kernel_wfp/Makefile.in
index efb214b..cfe643f 100644
--- a/src/libcharon/plugins/kernel_wfp/Makefile.in
+++ b/src/libcharon/plugins/kernel_wfp/Makefile.in
@@ -424,6 +424,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -439,7 +441,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c
index 95f79f1..e1c4298 100644
--- a/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c
+++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c
@@ -20,7 +20,6 @@
 #include "kernel_wfp_ipsec.h"
 
 #include <daemon.h>
-#include <hydra.h>
 #include <threading/mutex.h>
 #include <collections/array.h>
 #include <collections/hashtable.h>
@@ -1396,10 +1395,9 @@ static bool uninstall_route(private_kernel_wfp_ipsec_t *this,
 	{
 		if (--route->refs == 0)
 		{
-			if (hydra->kernel_interface->get_interface(hydra->kernel_interface,
-													   src, &name))
+			if (charon->kernel->get_interface(charon->kernel, src, &name))
 			{
-				res = hydra->kernel_interface->del_route(hydra->kernel_interface,
+				res = charon->kernel->del_route(charon->kernel,
 						dst->get_address(dst), mask, gtw, src, name) == SUCCESS;
 				free(name);
 			}
@@ -1442,10 +1440,9 @@ static bool install_route(private_kernel_wfp_ipsec_t *this,
 	}
 	else
 	{
-		if (hydra->kernel_interface->get_interface(hydra->kernel_interface,
-												   src, &name))
+		if (charon->kernel->get_interface(charon->kernel, src, &name))
 		{
-			if (hydra->kernel_interface->add_route(hydra->kernel_interface,
+			if (charon->kernel->add_route(charon->kernel,
 						dst->get_address(dst), mask, gtw, src, name) == SUCCESS)
 			{
 				INIT(route,
@@ -1486,14 +1483,13 @@ static bool manage_route(private_kernel_wfp_ipsec_t *this,
 	{
 		return FALSE;
 	}
-	if (hydra->kernel_interface->get_address_by_ts(hydra->kernel_interface,
-												src_ts, &src, NULL) != SUCCESS)
+	if (charon->kernel->get_address_by_ts(charon->kernel, src_ts, &src,
+										  NULL) != SUCCESS)
 	{
 		dst->destroy(dst);
 		return FALSE;
 	}
-	gtw = hydra->kernel_interface->get_nexthop(hydra->kernel_interface,
-											   remote, -1, local);
+	gtw = charon->kernel->get_nexthop(charon->kernel, remote, -1, local);
 	if (add)
 	{
 		done = install_route(this, dst, mask, src, gtw);
@@ -1650,8 +1646,7 @@ static void acquire(private_kernel_wfp_ipsec_t *this, UINT64 filter_id,
 	{
 		src = src ? src->clone(src) : NULL;
 		dst = dst ? dst->clone(dst) : NULL;
-		hydra->kernel_interface->acquire(hydra->kernel_interface, reqid,
-										 src, dst);
+		charon->kernel->acquire(charon->kernel, reqid, src, dst);
 	}
 }
 
@@ -2069,8 +2064,8 @@ static job_requeue_t expire_job(expire_data_t *data)
 
 	if (entry)
 	{
-		hydra->kernel_interface->expire(hydra->kernel_interface, protocol,
-										data->spi, data->dst, data->hard);
+		charon->kernel->expire(charon->kernel, protocol, data->spi, data->dst,
+							   data->hard);
 	}
 
 	return JOB_REQUEUE_NONE;
diff --git a/src/libcharon/plugins/led/Makefile.am b/src/libcharon/plugins/led/Makefile.am
index 18d6af3..9868f9e 100644
--- a/src/libcharon/plugins/led/Makefile.am
+++ b/src/libcharon/plugins/led/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/led/Makefile.in b/src/libcharon/plugins/led/Makefile.in
index 7942868..63bbf19 100644
--- a/src/libcharon/plugins/led/Makefile.in
+++ b/src/libcharon/plugins/led/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -428,7 +430,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/load_tester/Makefile.am b/src/libcharon/plugins/load_tester/Makefile.am
index 31e1b5c..af3adb2 100644
--- a/src/libcharon/plugins/load_tester/Makefile.am
+++ b/src/libcharon/plugins/load_tester/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
diff --git a/src/libcharon/plugins/load_tester/Makefile.in b/src/libcharon/plugins/load_tester/Makefile.in
index 52dbec5..14fcd6f 100644
--- a/src/libcharon/plugins/load_tester/Makefile.in
+++ b/src/libcharon/plugins/load_tester/Makefile.in
@@ -426,6 +426,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -441,7 +443,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c
index 8a50063..8f6abde 100644
--- a/src/libcharon/plugins/load_tester/load_tester_config.c
+++ b/src/libcharon/plugins/load_tester/load_tester_config.c
@@ -18,7 +18,6 @@
 #include <netdb.h>
 
 #include <daemon.h>
-#include <hydra.h>
 #include <attributes/mem_pool.h>
 #include <collections/hashtable.h>
 #include <threading/mutex.h>
@@ -656,8 +655,8 @@ static host_t *allocate_addr(private_load_tester_config_t *this, uint num)
 		id->destroy(id);
 		return NULL;
 	}
-	if (hydra->kernel_interface->add_ip(hydra->kernel_interface,
-										found, this->prefix, iface) != SUCCESS)
+	if (charon->kernel->add_ip(charon->kernel, found, this->prefix,
+							   iface) != SUCCESS)
 	{
 		DBG1(DBG_CFG, "installing load-tester IP %H on %s failed", found, iface);
 		found->destroy(found);
@@ -852,8 +851,8 @@ METHOD(load_tester_config_t, delete_ip, void,
 		{
 			if (pool->release_address(pool, entry->host, entry->id))
 			{
-				hydra->kernel_interface->del_ip(hydra->kernel_interface,
-											entry->host, this->prefix, FALSE);
+				charon->kernel->del_ip(charon->kernel, entry->host,
+									   this->prefix, FALSE);
 				break;
 			}
 		}
@@ -882,8 +881,8 @@ static void cleanup_leases(private_load_tester_config_t *this)
 		{
 			if (online)
 			{
-				hydra->kernel_interface->del_ip(hydra->kernel_interface,
-												addr, this->prefix, FALSE);
+				charon->kernel->del_ip(charon->kernel, addr, this->prefix,
+									   FALSE);
 				entry = this->leases->remove(this->leases, addr);
 				if (entry)
 				{
diff --git a/src/libcharon/plugins/load_tester/load_tester_plugin.c b/src/libcharon/plugins/load_tester/load_tester_plugin.c
index c7380b9..6cf3a90 100644
--- a/src/libcharon/plugins/load_tester/load_tester_plugin.c
+++ b/src/libcharon/plugins/load_tester/load_tester_plugin.c
@@ -23,7 +23,6 @@
 
 #include <unistd.h>
 
-#include <hydra.h>
 #include <daemon.h>
 #include <processing/jobs/callback_job.h>
 #include <threading/condvar.h>
@@ -240,16 +239,24 @@ METHOD(plugin_t, get_features, int,
 				PLUGIN_SDEPEND(PRIVKEY, KEY_RSA),
 				PLUGIN_SDEPEND(CERT_DECODE, CERT_ANY),
 				PLUGIN_SDEPEND(CERT_DECODE, CERT_X509),
+		PLUGIN_CALLBACK(kernel_ipsec_register, load_tester_ipsec_create),
+			PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"),
 	};
+	int count = countof(f);
+
 	*features = f;
-	return countof(f);
+
+	if (!lib->settings->get_bool(lib->settings,
+			"%s.plugins.load-tester.fake_kernel", FALSE, lib->ns))
+	{
+		count -= 2;
+	}
+	return count;
 }
 
 METHOD(plugin_t, destroy, void,
 	private_load_tester_plugin_t *this)
 {
-	hydra->kernel_interface->remove_ipsec_interface(hydra->kernel_interface,
-						(kernel_ipsec_constructor_t)load_tester_ipsec_create);
 	this->mutex->destroy(this->mutex);
 	this->condvar->destroy(this->condvar);
 	free(this);
@@ -289,12 +296,5 @@ plugin_t *load_tester_plugin_create()
 		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
 		.condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
 	);
-
-	if (lib->settings->get_bool(lib->settings,
-			"%s.plugins.load-tester.fake_kernel", FALSE, lib->ns))
-	{
-		hydra->kernel_interface->add_ipsec_interface(hydra->kernel_interface,
-						(kernel_ipsec_constructor_t)load_tester_ipsec_create);
-	}
 	return &this->public.plugin;
 }
diff --git a/src/libcharon/plugins/lookip/Makefile.am b/src/libcharon/plugins/lookip/Makefile.am
index 223654e..623275b 100644
--- a/src/libcharon/plugins/lookip/Makefile.am
+++ b/src/libcharon/plugins/lookip/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
diff --git a/src/libcharon/plugins/lookip/Makefile.in b/src/libcharon/plugins/lookip/Makefile.in
index 264c58f..9b56d94 100644
--- a/src/libcharon/plugins/lookip/Makefile.in
+++ b/src/libcharon/plugins/lookip/Makefile.in
@@ -422,6 +422,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -437,7 +439,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
diff --git a/src/libcharon/plugins/maemo/Makefile.am b/src/libcharon/plugins/maemo/Makefile.am
index fe5c963..02c283f 100644
--- a/src/libcharon/plugins/maemo/Makefile.am
+++ b/src/libcharon/plugins/maemo/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/maemo/Makefile.in b/src/libcharon/plugins/maemo/Makefile.in
index 76c9012..5cc6549 100644
--- a/src/libcharon/plugins/maemo/Makefile.in
+++ b/src/libcharon/plugins/maemo/Makefile.in
@@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -433,7 +435,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/medcli/Makefile.am b/src/libcharon/plugins/medcli/Makefile.am
index cfa8259..0408c89 100644
--- a/src/libcharon/plugins/medcli/Makefile.am
+++ b/src/libcharon/plugins/medcli/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/medcli/Makefile.in b/src/libcharon/plugins/medcli/Makefile.in
index 35740c3..32c4284 100644
--- a/src/libcharon/plugins/medcli/Makefile.in
+++ b/src/libcharon/plugins/medcli/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/medsrv/Makefile.am b/src/libcharon/plugins/medsrv/Makefile.am
index f212202..1d1cb44 100644
--- a/src/libcharon/plugins/medsrv/Makefile.am
+++ b/src/libcharon/plugins/medsrv/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/medsrv/Makefile.in b/src/libcharon/plugins/medsrv/Makefile.in
index 8fe160e..de0217a 100644
--- a/src/libcharon/plugins/medsrv/Makefile.in
+++ b/src/libcharon/plugins/medsrv/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/osx_attr/Makefile.am b/src/libcharon/plugins/osx_attr/Makefile.am
index aa1d462..908aa88 100644
--- a/src/libcharon/plugins/osx_attr/Makefile.am
+++ b/src/libcharon/plugins/osx_attr/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/osx_attr/Makefile.in b/src/libcharon/plugins/osx_attr/Makefile.in
index 9a5e438..6a1a81f 100644
--- a/src/libcharon/plugins/osx_attr/Makefile.in
+++ b/src/libcharon/plugins/osx_attr/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/p_cscf/Makefile.am b/src/libcharon/plugins/p_cscf/Makefile.am
new file mode 100644
index 0000000..1e00a56
--- /dev/null
+++ b/src/libcharon/plugins/p_cscf/Makefile.am
@@ -0,0 +1,19 @@
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libhydra \
+	-I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+	$(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-p-cscf.la
+else
+plugin_LTLIBRARIES = libstrongswan-p-cscf.la
+endif
+
+libstrongswan_p_cscf_la_SOURCES = \
+	p_cscf_plugin.c p_cscf_plugin.h \
+	p_cscf_handler.c p_cscf_handler.h
+
+libstrongswan_p_cscf_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/p_cscf/Makefile.in b/src/libcharon/plugins/p_cscf/Makefile.in
new file mode 100644
index 0000000..7f78db8
--- /dev/null
+++ b/src/libcharon/plugins/p_cscf/Makefile.in
@@ -0,0 +1,782 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 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.
+
+ at SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@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/libcharon/plugins/p_cscf
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+	$(top_srcdir)/m4/config/ltoptions.m4 \
+	$(top_srcdir)/m4/config/ltsugar.m4 \
+	$(top_srcdir)/m4/config/ltversion.m4 \
+	$(top_srcdir)/m4/config/lt~obsolete.m4 \
+	$(top_srcdir)/m4/macros/split-package-version.m4 \
+	$(top_srcdir)/m4/macros/with.m4 \
+	$(top_srcdir)/m4/macros/enable-disable.m4 \
+	$(top_srcdir)/m4/macros/add-plugin.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_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 = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_p_cscf_la_LIBADD =
+am_libstrongswan_p_cscf_la_OBJECTS = p_cscf_plugin.lo \
+	p_cscf_handler.lo
+libstrongswan_p_cscf_la_OBJECTS =  \
+	$(am_libstrongswan_p_cscf_la_OBJECTS)
+AM_V_lt = $(am__v_lt_ at AM_V@)
+am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+libstrongswan_p_cscf_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) $(libstrongswan_p_cscf_la_LDFLAGS) \
+	$(LDFLAGS) -o $@
+ at MONOLITHIC_FALSE@am_libstrongswan_p_cscf_la_rpath = -rpath \
+ at MONOLITHIC_FALSE@	$(plugindir)
+ at MONOLITHIC_TRUE@am_libstrongswan_p_cscf_la_rpath =
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_ at AM_V@)
+am__v_CC_ = $(am__v_CC_ at AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_ at AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_ at AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(libstrongswan_p_cscf_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_p_cscf_la_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GEM = @GEM@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
+PTHREADLIB = @PTHREADLIB@
+PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+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_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libhydra \
+	-I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+	$(PLUGIN_CFLAGS)
+
+ at MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-p-cscf.la
+ at MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-p-cscf.la
+libstrongswan_p_cscf_la_SOURCES = \
+	p_cscf_plugin.c p_cscf_plugin.h \
+	p_cscf_handler.c p_cscf_handler.h
+
+libstrongswan_p_cscf_la_LDFLAGS = -module -avoid-version
+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 ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/p_cscf/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/libcharon/plugins/p_cscf/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
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+	}
+
+uninstall-pluginLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+	done
+
+clean-pluginLTLIBRARIES:
+	-test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+	@list='$(plugin_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+
+libstrongswan-p-cscf.la: $(libstrongswan_p_cscf_la_OBJECTS) $(libstrongswan_p_cscf_la_DEPENDENCIES) $(EXTRA_libstrongswan_p_cscf_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(libstrongswan_p_cscf_la_LINK) $(am_libstrongswan_p_cscf_la_rpath) $(libstrongswan_p_cscf_la_OBJECTS) $(libstrongswan_p_cscf_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/p_cscf_handler.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/p_cscf_plugin.Plo at am__quote@
+
+.c.o:
+ at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+ at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+ at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+ at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+ at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+ at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+ at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+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 "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$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:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-noinstLTLIBRARIES \
+	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
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+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 TAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+	cscopelist-am ctags ctags-am 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 tags-am 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/libcharon/plugins/p_cscf/p_cscf_handler.c b/src/libcharon/plugins/p_cscf/p_cscf_handler.c
new file mode 100644
index 0000000..7663384
--- /dev/null
+++ b/src/libcharon/plugins/p_cscf/p_cscf_handler.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include "p_cscf_handler.h"
+
+#include <networking/host.h>
+#include <utils/debug.h>
+
+typedef struct private_p_cscf_handler_t private_p_cscf_handler_t;
+
+/**
+ * Private data
+ */
+struct private_p_cscf_handler_t {
+
+	/**
+	 * Public interface
+	 */
+	p_cscf_handler_t public;
+};
+
+METHOD(attribute_handler_t, handle, bool,
+	private_p_cscf_handler_t *this, ike_sa_t *ike_sa,
+	configuration_attribute_type_t type, chunk_t data)
+{
+	host_t *server;
+	int family = AF_INET6;
+
+	switch (type)
+	{
+		case P_CSCF_IP4_ADDRESS:
+			family = AF_INET;
+			/* fall-through */
+		case P_CSCF_IP6_ADDRESS:
+			server = host_create_from_chunk(family, data, 0);
+			if (!server)
+			{
+				DBG1(DBG_CFG, "received invalid P-CSCF server IP");
+				return FALSE;
+			}
+			DBG1(DBG_CFG, "received P-CSCF server IP %H", server);
+			server->destroy(server);
+			return TRUE;
+		default:
+			return FALSE;
+	}
+}
+
+METHOD(attribute_handler_t, release, void,
+	private_p_cscf_handler_t *this, ike_sa_t *ike_sa,
+	configuration_attribute_type_t type, chunk_t data)
+{
+	switch (type)
+	{
+		case P_CSCF_IP4_ADDRESS:
+		case P_CSCF_IP6_ADDRESS:
+			/* nothing to do as we only log the server IPs */
+			break;
+		default:
+			break;
+	}
+}
+
+/**
+ * Data for attribute enumerator
+ */
+typedef struct {
+	enumerator_t public;
+	bool request_ipv4;
+	bool request_ipv6;
+} attr_enumerator_t;
+
+METHOD(enumerator_t, enumerate_attrs, bool,
+	attr_enumerator_t *this, configuration_attribute_type_t *type,
+	chunk_t *data)
+{
+	if (this->request_ipv4)
+	{
+		*type = P_CSCF_IP4_ADDRESS;
+		*data = chunk_empty;
+		this->request_ipv4 = FALSE;
+		return TRUE;
+	}
+	if (this->request_ipv6)
+	{
+		*type = P_CSCF_IP6_ADDRESS;
+		*data = chunk_empty;
+		this->request_ipv6 = FALSE;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ * Check if the given host has a matching address family
+ */
+static bool is_family(host_t *host, int *family)
+{
+	return host->get_family(host) == *family;
+}
+
+/**
+ * Check if a list has a host of a given family
+ */
+static bool has_host_family(linked_list_t *list, int family)
+{
+	return list->find_first(list, (void*)is_family, NULL, &family) == SUCCESS;
+}
+
+METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
+	private_p_cscf_handler_t *this, ike_sa_t *ike_sa,
+	linked_list_t *vips)
+{
+	attr_enumerator_t *enumerator;
+
+	if (ike_sa->get_version(ike_sa) == IKEV1)
+	{
+		return enumerator_create_empty();
+	}
+
+	INIT(enumerator,
+		.public = {
+			.enumerate = (void*)_enumerate_attrs,
+			.destroy = (void*)free,
+		},
+	);
+	if (lib->settings->get_bool(lib->settings, "%s.plugins.p-cscf.enable.%s",
+								FALSE, lib->ns, ike_sa->get_name(ike_sa)))
+	{
+		enumerator->request_ipv4 = has_host_family(vips, AF_INET);
+		enumerator->request_ipv6 = has_host_family(vips, AF_INET6);
+	}
+	return &enumerator->public;
+}
+
+METHOD(p_cscf_handler_t, destroy, void,
+	private_p_cscf_handler_t *this)
+{
+	free(this);
+}
+
+/**
+ * See header
+ */
+p_cscf_handler_t *p_cscf_handler_create()
+{
+	private_p_cscf_handler_t *this;
+
+	INIT(this,
+		.public = {
+			.handler = {
+				.handle = _handle,
+				.release = _release,
+				.create_attribute_enumerator = _create_attribute_enumerator,
+			},
+			.destroy = _destroy,
+		},
+	);
+
+	return &this->public;
+}
diff --git a/src/libcharon/plugins/p_cscf/p_cscf_handler.h b/src/libcharon/plugins/p_cscf/p_cscf_handler.h
new file mode 100644
index 0000000..ad4f1ac
--- /dev/null
+++ b/src/libcharon/plugins/p_cscf/p_cscf_handler.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+/**
+ * @defgroup p_cscf_handler p_cscf_handler
+ * @{ @ingroup p_cscf
+ */
+
+#ifndef P_CSCF_HANDLER_H_
+#define P_CSCF_HANDLER_H_
+
+#include <attributes/attribute_handler.h>
+
+typedef struct p_cscf_handler_t p_cscf_handler_t;
+
+/**
+ * Attribute handler for P-CSCF server addresses.
+ */
+struct p_cscf_handler_t {
+
+	/**
+	 * Implements attribute_handler_t.
+	 */
+	attribute_handler_t handler;
+
+	/**
+	 * Destroy a p_cscf_handler_t.
+	 */
+	void (*destroy)(p_cscf_handler_t *this);
+};
+
+/**
+ * Create an p_cscf_handler_t instance.
+ */
+p_cscf_handler_t *p_cscf_handler_create();
+
+#endif /** P_CSCF_HANDLER_H_ @}*/
diff --git a/src/libcharon/plugins/p_cscf/p_cscf_plugin.c b/src/libcharon/plugins/p_cscf/p_cscf_plugin.c
new file mode 100644
index 0000000..8e2bc72
--- /dev/null
+++ b/src/libcharon/plugins/p_cscf/p_cscf_plugin.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include "p_cscf_plugin.h"
+#include "p_cscf_handler.h"
+
+#include <daemon.h>
+
+typedef struct private_p_cscf_plugin_t private_p_cscf_plugin_t;
+
+/**
+ * Private data
+ */
+struct private_p_cscf_plugin_t {
+
+	/**
+	 * Public interface
+	 */
+	p_cscf_plugin_t public;
+
+	/**
+	 * P-CSCF server address attribute handler
+	 */
+	p_cscf_handler_t *handler;
+};
+
+METHOD(plugin_t, get_name, char*,
+	private_p_cscf_plugin_t *this)
+{
+	return "p-cscf";
+}
+
+/**
+ * Register handler
+ */
+static bool plugin_cb(private_p_cscf_plugin_t *this,
+					  plugin_feature_t *feature, bool reg, void *cb_data)
+{
+	if (reg)
+	{
+		charon->attributes->add_handler(charon->attributes,
+										&this->handler->handler);
+	}
+	else
+	{
+		charon->attributes->remove_handler(charon->attributes,
+										   &this->handler->handler);
+	}
+	return TRUE;
+}
+
+METHOD(plugin_t, get_features, int,
+	private_p_cscf_plugin_t *this, plugin_feature_t *features[])
+{
+	static plugin_feature_t f[] = {
+		PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL),
+			PLUGIN_PROVIDE(CUSTOM, "p-cscf"),
+	};
+	*features = f;
+	return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+	private_p_cscf_plugin_t *this)
+{
+	this->handler->destroy(this->handler);
+	free(this);
+}
+
+/**
+ * See header
+ */
+plugin_t *p_cscf_plugin_create()
+{
+	private_p_cscf_plugin_t *this;
+
+	INIT(this,
+		.public = {
+			.plugin = {
+				.get_name = _get_name,
+				.get_features = _get_features,
+				.destroy = _destroy,
+			},
+		},
+		.handler = p_cscf_handler_create(),
+	);
+
+	return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/p_cscf/p_cscf_plugin.h b/src/libcharon/plugins/p_cscf/p_cscf_plugin.h
new file mode 100644
index 0000000..51b1767
--- /dev/null
+++ b/src/libcharon/plugins/p_cscf/p_cscf_plugin.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+/**
+ * @defgroup p_cscf p_cscf
+ * @ingroup cplugins
+ *
+ * @defgroup p_cscf_plugin p_cscf_plugin
+ * @{ @ingroup p_cscf
+ */
+
+#ifndef P_CSCF_PLUGIN_H_
+#define P_CSCF_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct p_cscf_plugin_t p_cscf_plugin_t;
+
+/**
+ * Plugin that requests P-CSCF server addresses from an ePDG as specified
+ * in RFC 7651.
+ */
+struct p_cscf_plugin_t {
+
+	/**
+	 * Implements plugin interface.
+	 */
+	plugin_t plugin;
+};
+
+#endif /** P_CSCF_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/radattr/Makefile.am b/src/libcharon/plugins/radattr/Makefile.am
index 15d5a0a..74d9351 100644
--- a/src/libcharon/plugins/radattr/Makefile.am
+++ b/src/libcharon/plugins/radattr/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libradius
 
diff --git a/src/libcharon/plugins/radattr/Makefile.in b/src/libcharon/plugins/radattr/Makefile.in
index baff3fc..3f39ba2 100644
--- a/src/libcharon/plugins/radattr/Makefile.in
+++ b/src/libcharon/plugins/radattr/Makefile.in
@@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -432,7 +434,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libradius
 
diff --git a/src/libcharon/plugins/resolve/Makefile.am b/src/libcharon/plugins/resolve/Makefile.am
index 9cfc370..d3d4e73 100644
--- a/src/libcharon/plugins/resolve/Makefile.am
+++ b/src/libcharon/plugins/resolve/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DRESOLV_CONF=\"${resolv_conf}\"
 
diff --git a/src/libcharon/plugins/resolve/Makefile.in b/src/libcharon/plugins/resolve/Makefile.in
index 91479bf..70d97cc 100644
--- a/src/libcharon/plugins/resolve/Makefile.in
+++ b/src/libcharon/plugins/resolve/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DRESOLV_CONF=\"${resolv_conf}\"
 
diff --git a/src/libcharon/plugins/resolve/resolve_handler.c b/src/libcharon/plugins/resolve/resolve_handler.c
index 74c3960..ec3decc 100644
--- a/src/libcharon/plugins/resolve/resolve_handler.c
+++ b/src/libcharon/plugins/resolve/resolve_handler.c
@@ -20,7 +20,6 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include <hydra.h>
 #include <utils/debug.h>
 #include <threading/mutex.h>
 
diff --git a/src/libcharon/plugins/smp/Makefile.am b/src/libcharon/plugins/smp/Makefile.am
index 3aa533e..252db32 100644
--- a/src/libcharon/plugins/smp/Makefile.am
+++ b/src/libcharon/plugins/smp/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
diff --git a/src/libcharon/plugins/smp/Makefile.in b/src/libcharon/plugins/smp/Makefile.in
index 572e7fc..221cda7 100644
--- a/src/libcharon/plugins/smp/Makefile.in
+++ b/src/libcharon/plugins/smp/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -429,7 +431,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
diff --git a/src/libcharon/plugins/smp/smp.c b/src/libcharon/plugins/smp/smp.c
index 2aa061f..56b19c7 100644
--- a/src/libcharon/plugins/smp/smp.c
+++ b/src/libcharon/plugins/smp/smp.c
@@ -229,8 +229,8 @@ static void request_query_ikesa(xmlTextReaderPtr reader, xmlTextWriterPtr writer
 		local = ike_sa->get_my_host(ike_sa);
 		xmlTextWriterStartElement(writer, "local");
 		xmlTextWriterWriteFormatElement(writer, "spi", "%.16llx",
-							id->is_initiator(id) ? id->get_initiator_spi(id)
-												 : id->get_responder_spi(id));
+					be64toh(id->is_initiator(id) ? id->get_initiator_spi(id)
+												 : id->get_responder_spi(id)));
 		write_id(writer, "identification", ike_sa->get_my_id(ike_sa));
 		write_address(writer, "address", local);
 		xmlTextWriterWriteFormatElement(writer, "port", "%d",
@@ -246,8 +246,8 @@ static void request_query_ikesa(xmlTextReaderPtr reader, xmlTextWriterPtr writer
 		remote = ike_sa->get_other_host(ike_sa);
 		xmlTextWriterStartElement(writer, "remote");
 		xmlTextWriterWriteFormatElement(writer, "spi", "%.16llx",
-							id->is_initiator(id) ? id->get_responder_spi(id)
-												 : id->get_initiator_spi(id));
+					be64toh(id->is_initiator(id) ? id->get_responder_spi(id)
+												 : id->get_initiator_spi(id)));
 		write_id(writer, "identification", ike_sa->get_other_id(ike_sa));
 		write_address(writer, "address", remote);
 		xmlTextWriterWriteFormatElement(writer, "port", "%d",
diff --git a/src/libcharon/plugins/socket_default/Makefile.am b/src/libcharon/plugins/socket_default/Makefile.am
index e524ffd..7231703 100644
--- a/src/libcharon/plugins/socket_default/Makefile.am
+++ b/src/libcharon/plugins/socket_default/Makefile.am
@@ -1,7 +1,6 @@
 AM_CPPFLAGS = \
 	-I${linux_headers} \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/socket_default/Makefile.in b/src/libcharon/plugins/socket_default/Makefile.in
index 25b4099..3dcfaf4 100644
--- a/src/libcharon/plugins/socket_default/Makefile.in
+++ b/src/libcharon/plugins/socket_default/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -432,7 +434,6 @@ xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I${linux_headers} \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c
index 13bf3e7..6e432d9 100644
--- a/src/libcharon/plugins/socket_default/socket_default_socket.c
+++ b/src/libcharon/plugins/socket_default/socket_default_socket.c
@@ -41,7 +41,6 @@
 #include <netinet/udp.h>
 #include <net/if.h>
 
-#include <hydra.h>
 #include <daemon.h>
 #include <threading/thread.h>
 
@@ -720,16 +719,15 @@ static int open_socket(private_socket_default_socket_t *this,
 	}
 #endif
 
-	if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface,
-												skt, family))
+	if (!charon->kernel->bypass_socket(charon->kernel, skt, family))
 	{
 		DBG1(DBG_NET, "installing IKE bypass policy failed");
 	}
 
 	/* enable UDP decapsulation for NAT-T sockets */
 	if (port == &this->natt &&
-		!hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface,
-												   skt, family, this->natt))
+		!charon->kernel->enable_udp_decap(charon->kernel, skt, family,
+										  this->natt))
 	{
 		DBG1(DBG_NET, "enabling UDP decapsulation for %s on port %d failed",
 			 family == AF_INET ? "IPv4" : "IPv6", this->natt);
diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.am b/src/libcharon/plugins/socket_dynamic/Makefile.am
index a1e21b9..087ebb7 100644
--- a/src/libcharon/plugins/socket_dynamic/Makefile.am
+++ b/src/libcharon/plugins/socket_dynamic/Makefile.am
@@ -1,7 +1,6 @@
 AM_CPPFLAGS = \
 	-I${linux_headers} \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.in b/src/libcharon/plugins/socket_dynamic/Makefile.in
index 5c010a5..88bc22f 100644
--- a/src/libcharon/plugins/socket_dynamic/Makefile.in
+++ b/src/libcharon/plugins/socket_dynamic/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -432,7 +434,6 @@ xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I${linux_headers} \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
index a032134..b89cae4 100644
--- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
+++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
@@ -36,7 +36,6 @@
 #include <netinet/udp.h>
 #include <net/if.h>
 
-#include <hydra.h>
 #include <daemon.h>
 #include <threading/thread.h>
 #include <threading/rwlock.h>
@@ -438,15 +437,13 @@ static int open_socket(private_socket_dynamic_socket_t *this,
 		return 0;
 	}
 
-	if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface,
-												fd, family))
+	if (!charon->kernel->bypass_socket(charon->kernel, fd, family))
 	{
 		DBG1(DBG_NET, "installing IKE bypass policy failed");
 	}
 
 	/* enable UDP decapsulation on each socket */
-	if (!hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface,
-												   fd, family, *port))
+	if (!charon->kernel->enable_udp_decap(charon->kernel, fd, family, *port))
 	{
 		DBG1(DBG_NET, "enabling UDP decapsulation for %s on port %d failed",
 			 family == AF_INET ? "IPv4" : "IPv6", *port);
diff --git a/src/libcharon/plugins/socket_win/Makefile.am b/src/libcharon/plugins/socket_win/Makefile.am
index f01178f..293d9bc 100644
--- a/src/libcharon/plugins/socket_win/Makefile.am
+++ b/src/libcharon/plugins/socket_win/Makefile.am
@@ -1,7 +1,6 @@
 AM_CPPFLAGS = \
 	-I${linux_headers} \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/socket_win/Makefile.in b/src/libcharon/plugins/socket_win/Makefile.in
index 0c3bf31..6830110 100644
--- a/src/libcharon/plugins/socket_win/Makefile.in
+++ b/src/libcharon/plugins/socket_win/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -432,7 +434,6 @@ xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I${linux_headers} \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/socket_win/socket_win_socket.c b/src/libcharon/plugins/socket_win/socket_win_socket.c
index fbfbeda..94af08e 100644
--- a/src/libcharon/plugins/socket_win/socket_win_socket.c
+++ b/src/libcharon/plugins/socket_win/socket_win_socket.c
@@ -19,7 +19,6 @@
 #include "socket_win_socket.h"
 
 #include <library.h>
-#include <hydra.h>
 #include <threading/thread.h>
 #include <daemon.h>
 
@@ -397,13 +396,11 @@ static SOCKET open_socket(private_socket_win_socket_t *this, int i)
 		closesocket(s);
 		return INVALID_SOCKET;
 	}
-	if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface,
-												s, AF_INET))
+	if (!charon->kernel->bypass_socket(charon->kernel, s, AF_INET))
 	{
 		DBG1(DBG_NET, "installing IPv4 IKE bypass policy failed");
 	}
-	if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface,
-												s, AF_INET6))
+	if (!charon->kernel->bypass_socket(charon->kernel, s, AF_INET6))
 	{
 		DBG1(DBG_NET, "installing IPv6 IKE bypass policy failed");
 	}
diff --git a/src/libcharon/plugins/sql/Makefile.am b/src/libcharon/plugins/sql/Makefile.am
index c947db8..44a3d5f 100644
--- a/src/libcharon/plugins/sql/Makefile.am
+++ b/src/libcharon/plugins/sql/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/sql/Makefile.in b/src/libcharon/plugins/sql/Makefile.in
index f74257a..b09379b 100644
--- a/src/libcharon/plugins/sql/Makefile.in
+++ b/src/libcharon/plugins/sql/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -429,7 +431,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/stroke/Makefile.am b/src/libcharon/plugins/stroke/Makefile.am
index b906887..26edc3d 100644
--- a/src/libcharon/plugins/stroke/Makefile.am
+++ b/src/libcharon/plugins/stroke/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/stroke \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\" \
diff --git a/src/libcharon/plugins/stroke/Makefile.in b/src/libcharon/plugins/stroke/Makefile.in
index a316f5c..2b22b33 100644
--- a/src/libcharon/plugins/stroke/Makefile.in
+++ b/src/libcharon/plugins/stroke/Makefile.in
@@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -433,7 +435,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/stroke \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\" \
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index 68cf830..d0eb2aa 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -16,7 +16,6 @@
 
 #include "stroke_config.h"
 
-#include <hydra.h>
 #include <daemon.h>
 #include <threading/mutex.h>
 #include <utils/lexparser.h>
@@ -201,8 +200,7 @@ static bool is_local(char *address, bool any_allowed)
 			host = host_create_from_dns(token, 0, 0);
 			if (host)
 			{
-				if (hydra->kernel_interface->get_interface(
-										hydra->kernel_interface, host, NULL))
+				if (charon->kernel->get_interface(charon->kernel, host, NULL))
 				{
 					found = TRUE;
 				}
@@ -313,117 +311,6 @@ static void build_crl_policy(auth_cfg_t *cfg, bool local, int policy)
 }
 
 /**
- * Parse public key / signature strength constraints
- */
-static void parse_pubkey_constraints(char *auth, auth_cfg_t *cfg)
-{
-	enumerator_t *enumerator;
-	bool rsa = FALSE, ecdsa = FALSE, bliss = FALSE,
-		 rsa_len = FALSE, ecdsa_len = FALSE, bliss_strength = FALSE;
-	int strength;
-	char *token;
-
-	enumerator = enumerator_create_token(auth, "-", "");
-	while (enumerator->enumerate(enumerator, &token))
-	{
-		bool found = FALSE;
-		int i;
-		struct {
-			char *name;
-			signature_scheme_t scheme;
-			key_type_t key;
-		} schemes[] = {
-			{ "md5",		SIGN_RSA_EMSA_PKCS1_MD5,		KEY_RSA,	},
-			{ "sha1",		SIGN_RSA_EMSA_PKCS1_SHA1,		KEY_RSA,	},
-			{ "sha224",		SIGN_RSA_EMSA_PKCS1_SHA224,		KEY_RSA,	},
-			{ "sha256",		SIGN_RSA_EMSA_PKCS1_SHA256,		KEY_RSA,	},
-			{ "sha384",		SIGN_RSA_EMSA_PKCS1_SHA384,		KEY_RSA,	},
-			{ "sha512",		SIGN_RSA_EMSA_PKCS1_SHA512,		KEY_RSA,	},
-			{ "sha1",		SIGN_ECDSA_WITH_SHA1_DER,		KEY_ECDSA,	},
-			{ "sha256",		SIGN_ECDSA_WITH_SHA256_DER,		KEY_ECDSA,	},
-			{ "sha384",		SIGN_ECDSA_WITH_SHA384_DER,		KEY_ECDSA,	},
-			{ "sha512",		SIGN_ECDSA_WITH_SHA512_DER,		KEY_ECDSA,	},
-			{ "sha256",		SIGN_ECDSA_256,					KEY_ECDSA,	},
-			{ "sha384",		SIGN_ECDSA_384,					KEY_ECDSA,	},
-			{ "sha512",		SIGN_ECDSA_521,					KEY_ECDSA,	},
-			{ "sha256",		SIGN_BLISS_WITH_SHA2_256,		KEY_BLISS,	},
-			{ "sha384",		SIGN_BLISS_WITH_SHA2_384,		KEY_BLISS,	},
-			{ "sha512",		SIGN_BLISS_WITH_SHA2_512,		KEY_BLISS,	},
-		};
-
-		if (rsa_len || ecdsa_len || bliss_strength)
-		{	/* expecting a key strength token */
-			strength = atoi(token);
-			if (strength)
-			{
-				if (rsa_len)
-				{
-					cfg->add(cfg, AUTH_RULE_RSA_STRENGTH, (uintptr_t)strength);
-				}
-				else if (ecdsa_len)
-				{
-					cfg->add(cfg, AUTH_RULE_ECDSA_STRENGTH, (uintptr_t)strength);
-				}
-				else if (bliss_strength)
-				{
-					cfg->add(cfg, AUTH_RULE_BLISS_STRENGTH, (uintptr_t)strength);
-				}
-			}
-			rsa_len = ecdsa_len = bliss_strength = FALSE;
-			if (strength)
-			{
-				continue;
-			}
-		}
-		if (streq(token, "rsa"))
-		{
-			rsa = rsa_len = TRUE;
-			continue;
-		}
-		if (streq(token, "ecdsa"))
-		{
-			ecdsa = ecdsa_len = TRUE;
-			continue;
-		}
-		if (streq(token, "bliss"))
-		{
-			bliss = bliss_strength = TRUE;
-			continue;
-		}
-		if (streq(token, "pubkey"))
-		{
-			continue;
-		}
-
-		for (i = 0; i < countof(schemes); i++)
-		{
-			if (streq(schemes[i].name, token))
-			{
-				/* for each matching string, allow the scheme, if:
-				 * - it is an RSA scheme, and we enforced RSA
-				 * - it is an ECDSA scheme, and we enforced ECDSA
-				 * - it is not a key type specific scheme
-				 */
-				if ((rsa && schemes[i].key == KEY_RSA) ||
-					(ecdsa && schemes[i].key == KEY_ECDSA) ||
-					(bliss && schemes[i].key == KEY_BLISS) ||
-					(!rsa && !ecdsa && !bliss))
-				{
-					cfg->add(cfg, AUTH_RULE_SIGNATURE_SCHEME,
-							 (uintptr_t)schemes[i].scheme);
-				}
-				found = TRUE;
-			}
-		}
-		if (!found)
-		{
-			DBG1(DBG_CFG, "ignoring invalid auth token: '%s'", token);
-		}
-	}
-	enumerator->destroy(enumerator);
-}
-
-/**
  * build authentication config
  */
 static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
@@ -619,15 +506,15 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
 	}
 
 	/* authentication metod (class, actually) */
-	if (strpfx(auth, "pubkey") ||
+	if (strpfx(auth, "ike:") ||
+		strpfx(auth, "pubkey") ||
 		strpfx(auth, "rsa") ||
 		strpfx(auth, "ecdsa") ||
 		strpfx(auth, "bliss"))
 	{
 		cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
 		build_crl_policy(cfg, local, msg->add_conn.crl_policy);
-
-		parse_pubkey_constraints(auth, cfg);
+		cfg->add_pubkey_constraints(cfg, auth, TRUE);
 	}
 	else if (streq(auth, "psk") || streq(auth, "secret"))
 	{
@@ -660,7 +547,7 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
 		if (pos)
 		{
 			*pos = 0;
-			parse_pubkey_constraints(pos + 1, cfg);
+			cfg->add_pubkey_constraints(cfg, pos + 1, FALSE);
 		}
 		type = eap_vendor_type_from_string(auth);
 		if (type)
diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c
index 5a1a507..36da5ff 100644
--- a/src/libcharon/plugins/stroke/stroke_control.c
+++ b/src/libcharon/plugins/stroke/stroke_control.c
@@ -16,7 +16,6 @@
 
 #include "stroke_control.h"
 
-#include <hydra.h>
 #include <daemon.h>
 
 #include <processing/jobs/delete_ike_sa_job.h>
diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c
index c0192b5..0371c70 100644
--- a/src/libcharon/plugins/stroke/stroke_list.c
+++ b/src/libcharon/plugins/stroke/stroke_list.c
@@ -2,6 +2,9 @@
  * Copyright (C) 2008 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR 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
@@ -23,22 +26,12 @@
 #include <malloc.h>
 #endif /* HAVE_MALLINFO */
 
-#include <hydra.h>
 #include <daemon.h>
 #include <collections/linked_list.h>
 #include <plugins/plugin.h>
 #include <credentials/certificates/x509.h>
-#include <credentials/certificates/ac.h>
-#include <credentials/certificates/crl.h>
-#include <credentials/certificates/pgp_certificate.h>
+#include <credentials/certificates/certificate_printer.h>
 #include <config/peer_cfg.h>
-#include <asn1/asn1.h>
-#include <asn1/oid.h>
-
-/* warning intervals for list functions */
-#define CERT_WARNING_INTERVAL  30	/* days */
-#define CRL_WARNING_INTERVAL	7	/* days */
-#define AC_WARNING_INTERVAL		1	/* day */
 
 typedef struct private_stroke_list_t private_stroke_list_t;
 
@@ -69,6 +62,11 @@ struct private_stroke_list_t {
 };
 
 /**
+ * Static certificate printer object
+ */
+static certificate_printer_t *cert_printer = NULL;
+
+/**
  * Log tasks of a specific queue to out
  */
 static void log_task_q(FILE *out, ike_sa_t *ike_sa, task_queue_t q, char *name)
@@ -139,8 +137,10 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
 		fprintf(out, "%12s[%d]: %N SPIs: %.16"PRIx64"_i%s %.16"PRIx64"_r%s",
 				ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
 				ike_version_names, ike_sa->get_version(ike_sa),
-				id->get_initiator_spi(id), id->is_initiator(id) ? "*" : "",
-				id->get_responder_spi(id), id->is_initiator(id) ? "" : "*");
+				be64toh(id->get_initiator_spi(id)),
+				id->is_initiator(id) ? "*" : "",
+				be64toh(id->get_responder_spi(id)),
+				id->is_initiator(id) ? "" : "*");
 
 
 		if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
@@ -244,40 +244,36 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
 			proposal = child_sa->get_proposal(child_sa);
 			if (proposal)
 			{
-				u_int16_t encr_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED;
-				u_int16_t encr_size = 0, int_size = 0;
-				u_int16_t esn = NO_EXT_SEQ_NUMBERS;
+				u_int16_t alg, ks;
 				bool first = TRUE;
 
-				proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
-										&encr_alg, &encr_size);
-				proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
-										&int_alg, &int_size);
-				proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
-										&esn, NULL);
-
-				if (encr_alg != ENCR_UNDEFINED)
+				if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
+											&alg, &ks) && alg != ENCR_UNDEFINED)
 				{
-					fprintf(out, "%N", encryption_algorithm_names, encr_alg);
+					fprintf(out, "%N", encryption_algorithm_names, alg);
 					first = FALSE;
-					if (encr_size)
+					if (ks)
 					{
-						fprintf(out, "_%u", encr_size);
+						fprintf(out, "_%u", ks);
 					}
 				}
-				if (int_alg != AUTH_UNDEFINED)
+				if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
+											&alg, &ks) && alg != AUTH_UNDEFINED)
 				{
-					if (!first)
-					{
-						fprintf(out, "/");
-					}
-					fprintf(out, "%N", integrity_algorithm_names, int_alg);
-					if (int_size)
+					fprintf(out, "%s%N", first ? "" : "/",
+							integrity_algorithm_names, alg);
+					if (ks)
 					{
-						fprintf(out, "_%u", int_size);
+						fprintf(out, "_%u", ks);
 					}
 				}
-				if (esn == EXT_SEQ_NUMBERS)
+				if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
+											&alg, NULL))
+				{
+					fprintf(out, "/%N", diffie_hellman_group_names, alg);
+				}
+				if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
+											&alg, NULL) && alg == EXT_SEQ_NUMBERS)
 				{
 					fprintf(out, "/ESN");
 				}
@@ -538,8 +534,8 @@ METHOD(stroke_list_t, status, void,
 		}
 		enumerator->destroy(enumerator);
 
-		enumerator = hydra->kernel_interface->create_address_enumerator(
-								hydra->kernel_interface, ADDR_TYPE_REGULAR);
+		enumerator = charon->kernel->create_address_enumerator(charon->kernel,
+															ADDR_TYPE_REGULAR);
 		fprintf(out, "Listening IP addresses:\n");
 		while (enumerator->enumerate(enumerator, (void**)&host))
 		{
@@ -738,14 +734,20 @@ static linked_list_t* create_unique_cert_list(certificate_type_t type)
 }
 
 /**
- * Print a single public key.
+ * Is there a matching private key?
  */
-static void list_public_key(public_key_t *public, FILE *out)
+static bool has_privkey(certificate_t *cert)
 {
+	public_key_t *public;
 	private_key_t *private = NULL;
 	chunk_t keyid;
 	identification_t *id;
 
+	public = cert->get_public_key(cert);
+	if (!public)
+	{
+		return FALSE;
+	}
 	if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyid))
 	{
 		id = identification_create_from_encoding(ID_KEY_ID, keyid);
@@ -753,521 +755,56 @@ static void list_public_key(public_key_t *public, FILE *out)
 									public->get_type(public), id, NULL);
 		id->destroy(id);
 	}
-
-	fprintf(out, "  pubkey:    %N %d bits%s\n",
-			key_type_names, public->get_type(public),
-			public->get_keysize(public),
-			private ? ", has private key" : "");
-	if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid))
-	{
-		fprintf(out, "  keyid:     %#B\n", &keyid);
-	}
-	if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyid))
-	{
-		fprintf(out, "  subjkey:   %#B\n", &keyid);
-	}
+	public->destroy(public);
 	DESTROY_IF(private);
-}
-
-/**
- * list all raw public keys
- */
-static void stroke_list_pubkeys(linked_list_t *list, bool utc, FILE *out)
-{
-	bool first = TRUE;
-	time_t now = time(NULL), notBefore, notAfter;
-	enumerator_t *enumerator;
-	certificate_t *cert;
-
-	enumerator = list->create_enumerator(list);
-	while (enumerator->enumerate(enumerator, (void**)&cert))
-	{
-		identification_t *subject = cert->get_subject(cert);
-		public_key_t *public = cert->get_public_key(cert);
-
-		if (public)
-		{
-			if (first)
-			{
-				fprintf(out, "\n");
-				fprintf(out, "List of Raw Public Keys:\n");
-				first = FALSE;
-			}
-			fprintf(out, "\n");
-
-			/* list subject if available */
-			if (subject->get_type(subject) != ID_KEY_ID)
-			{
-				fprintf(out, "  subject:   %#Y\n", subject);
-			}
-
-			/* list validity if available*/
-			cert->get_validity(cert, &now, &notBefore, &notAfter);
-			if (notBefore != UNDEFINED_TIME && notAfter != UNDEFINED_TIME)
-			{
-				fprintf(out, "  validity:  not before %T, ", &notBefore, utc);
-				if (now < notBefore)
-				{
-					fprintf(out, "not valid yet (valid in %V)\n", &now, &notBefore);
-				}
-				else
-				{
-					fprintf(out, "ok\n");
-				}
-				fprintf(out, "             not after  %T, ", &notAfter, utc);
-				if (now > notAfter)
-				{
-					fprintf(out, "expired (%V ago)\n", &now, &notAfter);
-				}
-				else
-				{
-					fprintf(out, "ok");
-					if (now > notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24)
-					{
-						fprintf(out, " (expires in %V)", &now, &notAfter);
-					}
-					fprintf(out, " \n");
-				}
-			}
-
-			list_public_key(public, out);
-			public->destroy(public);
-		}
-	}
-	enumerator->destroy(enumerator);
-}
-
-/**
- * list OpenPGP certificates
- */
-static void stroke_list_pgp(linked_list_t *list,bool utc, FILE *out)
-{
-	bool first = TRUE;
-	time_t now = time(NULL);
-	enumerator_t *enumerator = list->create_enumerator(list);
-	certificate_t *cert;
-
-	while (enumerator->enumerate(enumerator, (void**)&cert))
-	{
-		time_t created, until;
-		public_key_t *public;
-		pgp_certificate_t *pgp_cert = (pgp_certificate_t*)cert;
-		chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert);
-
-		if (first)
-		{
 
-			fprintf(out, "\n");
-				fprintf(out, "List of PGP End Entity Certificates:\n");
-				first = FALSE;
-		}
-		fprintf(out, "\n");
-		fprintf(out, "  userid:   '%Y'\n", cert->get_subject(cert));
-
-		fprintf(out, "  digest:    %#B\n", &fingerprint);
-
-		/* list validity */
-		cert->get_validity(cert, &now, &created, &until);
-		fprintf(out, "  created:   %T\n", &created, utc);
-		fprintf(out, "  until:     %T%s\n", &until, utc,
-			(until == TIME_32_BIT_SIGNED_MAX) ? " (expires never)":"");
-
-		public = cert->get_public_key(cert);
-		if (public)
-		{
-			list_public_key(public, out);
-			public->destroy(public);
-		}
-	}
-	enumerator->destroy(enumerator);
+	return (private != NULL);
 }
 
 /**
  * list all X.509 certificates matching the flags
  */
-static void stroke_list_certs(linked_list_t *list, char *label,
-							  x509_flag_t flags, bool utc, FILE *out)
+static void stroke_list_x509_certs(linked_list_t *list, x509_flag_t flag)
 {
-	bool first = TRUE;
-	time_t now = time(NULL);
 	enumerator_t *enumerator;
 	certificate_t *cert;
-	x509_flag_t flag_mask;
-
-	/* mask all auxiliary flags */
-	flag_mask = ~(X509_SERVER_AUTH | X509_CLIENT_AUTH | X509_IKE_INTERMEDIATE |
-				  X509_SELF_SIGNED | X509_IP_ADDR_BLOCKS);
 
 	enumerator = list->create_enumerator(list);
 	while (enumerator->enumerate(enumerator, (void**)&cert))
 	{
 		x509_t *x509 = (x509_t*)cert;
-		x509_flag_t x509_flags = x509->get_flags(x509) & flag_mask;
+		x509_flag_t flags = x509->get_flags(x509) & X509_ANY;
 
 		/* list only if flag is set or flag == 0 */
-		if ((x509_flags & flags) || (x509_flags == flags))
+		if ((flags & flag) || flags == flag)
 		{
-			enumerator_t *enumerator;
-			identification_t *altName;
-			bool first_altName = TRUE;
-			u_int pathlen;
-			chunk_t serial, authkey;
-			time_t notBefore, notAfter;
-			public_key_t *public;
-
-			if (first)
-			{
-				fprintf(out, "\n");
-				fprintf(out, "List of %s:\n", label);
-				first = FALSE;
-			}
-			fprintf(out, "\n");
-
-			/* list subjectAltNames */
-			enumerator = x509->create_subjectAltName_enumerator(x509);
-			while (enumerator->enumerate(enumerator, (void**)&altName))
-			{
-				if (first_altName)
-				{
-					fprintf(out, "  altNames:  ");
-					first_altName = FALSE;
-				}
-				else
-				{
-					fprintf(out, ", ");
-				}
-				fprintf(out, "%Y", altName);
-			}
-			if (!first_altName)
-			{
-				fprintf(out, "\n");
-			}
-			enumerator->destroy(enumerator);
-
-			fprintf(out, "  subject:  \"%Y\"\n", cert->get_subject(cert));
-			fprintf(out, "  issuer:   \"%Y\"\n", cert->get_issuer(cert));
-			serial = chunk_skip_zero(x509->get_serial(x509));
-			fprintf(out, "  serial:    %#B\n", &serial);
-
-			/* list validity */
-			cert->get_validity(cert, &now, &notBefore, &notAfter);
-			fprintf(out, "  validity:  not before %T, ", &notBefore, utc);
-			if (now < notBefore)
-			{
-				fprintf(out, "not valid yet (valid in %V)\n", &now, &notBefore);
-			}
-			else
-			{
-				fprintf(out, "ok\n");
-			}
-			fprintf(out, "             not after  %T, ", &notAfter, utc);
-			if (now > notAfter)
-			{
-				fprintf(out, "expired (%V ago)\n", &now, &notAfter);
-			}
-			else
-			{
-				fprintf(out, "ok");
-				if (now > notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24)
-				{
-					fprintf(out, " (expires in %V)", &now, &notAfter);
-				}
-				fprintf(out, " \n");
-			}
-
-			public = cert->get_public_key(cert);
-			if (public)
-			{
-				list_public_key(public, out);
-				public->destroy(public);
-			}
-
-			/* list optional authorityKeyIdentifier */
-			authkey = x509->get_authKeyIdentifier(x509);
-			if (authkey.ptr)
-			{
-				fprintf(out, "  authkey:   %#B\n", &authkey);
-			}
-
-			/* list optional pathLenConstraint */
-			pathlen = x509->get_constraint(x509, X509_PATH_LEN);
-			if (pathlen != X509_NO_CONSTRAINT)
-			{
-				fprintf(out, "  pathlen:   %u\n", pathlen);
-			}
-
-			/* list optional ipAddrBlocks */
-			if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
-			{
-				traffic_selector_t *ipAddrBlock;
-				bool first_ipAddrBlock = TRUE;
-
-				fprintf(out, "  addresses: ");
-				enumerator = x509->create_ipAddrBlock_enumerator(x509);
-				while (enumerator->enumerate(enumerator, &ipAddrBlock))
-				{
-					if (first_ipAddrBlock)
-					{
-						first_ipAddrBlock = FALSE;
-					}
-					else
-					{
-						fprintf(out, ", ");
-					}
-					fprintf(out, "%R", ipAddrBlock);
-				}
-				enumerator->destroy(enumerator);
-				fprintf(out, "\n");
-			}
+			cert_printer->print_caption(cert_printer, CERT_X509, flag);
+			cert_printer->print(cert_printer, cert, has_privkey(cert));
 		}
 	}
 	enumerator->destroy(enumerator);
 }
 
 /**
- * list all X.509 attribute certificates
+ * list all other certificates types
  */
-static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out)
+static void stroke_list_other_certs(certificate_type_t type)
 {
-	bool first = TRUE;
-	time_t notBefore, notAfter, now = time(NULL);
 	enumerator_t *enumerator;
 	certificate_t *cert;
+	linked_list_t *list;
+
+	list = create_unique_cert_list(type);
 
 	enumerator = list->create_enumerator(list);
 	while (enumerator->enumerate(enumerator, &cert))
 	{
-		ac_t *ac = (ac_t*)cert;
-		ac_group_type_t type;
-		identification_t *id;
-		enumerator_t *groups;
-		chunk_t chunk;
-		bool firstgroup = TRUE;
-
-		if (first)
-		{
-			fprintf(out, "\n");
-			fprintf(out, "List of X.509 Attribute Certificates:\n");
-			first = FALSE;
-		}
-		fprintf(out, "\n");
-
-		id = cert->get_subject(cert);
-		if (id)
-		{
-			fprintf(out, "  holder:   \"%Y\"\n", id);
-		}
-		id = ac->get_holderIssuer(ac);
-		if (id)
-		{
-			fprintf(out, "  hissuer:  \"%Y\"\n", id);
-		}
-		chunk = chunk_skip_zero(ac->get_holderSerial(ac));
-		if (chunk.ptr)
-		{
-			fprintf(out, "  hserial:   %#B\n", &chunk);
-		}
-		groups = ac->create_group_enumerator(ac);
-		while (groups->enumerate(groups, &type, &chunk))
-		{
-			int oid;
-			char *str;
-
-			if (firstgroup)
-			{
-				fprintf(out, "  groups:    ");
-				firstgroup = FALSE;
-			}
-			else
-			{
-				fprintf(out, "             ");
-			}
-			switch (type)
-			{
-				case AC_GROUP_TYPE_STRING:
-					fprintf(out, "%.*s", (int)chunk.len, chunk.ptr);
-					break;
-				case AC_GROUP_TYPE_OID:
-					oid = asn1_known_oid(chunk);
-					if (oid == OID_UNKNOWN)
-					{
-						str = asn1_oid_to_string(chunk);
-						if (str)
-						{
-							fprintf(out, "%s", str);
-							free(str);
-						}
-						else
-						{
-							fprintf(out, "OID:%#B", &chunk);
-						}
-					}
-					else
-					{
-						fprintf(out, "%s", oid_names[oid].name);
-					}
-					break;
-				case AC_GROUP_TYPE_OCTETS:
-					fprintf(out, "%#B", &chunk);
-					break;
-			}
-			fprintf(out, "\n");
-		}
-		groups->destroy(groups);
-		fprintf(out, "  issuer:   \"%Y\"\n", cert->get_issuer(cert));
-		chunk  = chunk_skip_zero(ac->get_serial(ac));
-		fprintf(out, "  serial:    %#B\n", &chunk);
-
-		/* list validity */
-		cert->get_validity(cert, &now, &notBefore, &notAfter);
-		fprintf(out, "  validity:  not before %T, ", &notBefore, utc);
-		if (now < notBefore)
-		{
-			fprintf(out, "not valid yet (valid in %V)\n", &now, &notBefore);
-		}
-		else
-		{
-			fprintf(out, "ok\n");
-		}
-		fprintf(out, "             not after  %T, ", &notAfter, utc);
-		if (now > notAfter)
-		{
-			fprintf(out, "expired (%V ago)\n", &now, &notAfter);
-		}
-		else
-		{
-			fprintf(out, "ok");
-			if (now > notAfter - AC_WARNING_INTERVAL * 60 * 60 * 24)
-			{
-				fprintf(out, " (expires in %V)", &now, &notAfter);
-			}
-			fprintf(out, " \n");
-		}
-
-		/* list optional authorityKeyIdentifier */
-		chunk = ac->get_authKeyIdentifier(ac);
-		if (chunk.ptr)
-		{
-			fprintf(out, "  authkey:   %#B\n", &chunk);
-		}
+		cert_printer->print_caption(cert_printer, cert->get_type(cert), X509_NONE);
+		cert_printer->print(cert_printer, cert, has_privkey(cert));
 	}
 	enumerator->destroy(enumerator);
-}
-
-/**
- * list all X.509 CRLs
- */
-static void stroke_list_crls(linked_list_t *list, bool utc, FILE *out)
-{
-	bool first = TRUE;
-	time_t thisUpdate, nextUpdate, now = time(NULL);
-	enumerator_t *enumerator = list->create_enumerator(list);
-	certificate_t *cert;
 
-	while (enumerator->enumerate(enumerator, (void**)&cert))
-	{
-		crl_t *crl = (crl_t*)cert;
-		chunk_t chunk;
-
-		if (first)
-		{
-			fprintf(out, "\n");
-			fprintf(out, "List of X.509 CRLs:\n");
-			first = FALSE;
-		}
-		fprintf(out, "\n");
-
-		fprintf(out, "  issuer:   \"%Y\"\n", cert->get_issuer(cert));
-
-		/* list optional crlNumber */
-		chunk = chunk_skip_zero(crl->get_serial(crl));
-		if (chunk.ptr)
-		{
-			fprintf(out, "  serial:    %#B\n", &chunk);
-		}
-		if (crl->is_delta_crl(crl, &chunk))
-		{
-			chunk = chunk_skip_zero(chunk);
-			fprintf(out, "  delta for: %#B\n", &chunk);
-		}
-
-		/* count the number of revoked certificates */
-		{
-			int count = 0;
-			enumerator_t *enumerator = crl->create_enumerator(crl);
-
-			while (enumerator->enumerate(enumerator, NULL, NULL, NULL))
-			{
-				count++;
-			}
-			fprintf(out, "  revoked:   %d certificate%s\n", count,
-							(count == 1)? "" : "s");
-			enumerator->destroy(enumerator);
-		}
-
-		/* list validity */
-		cert->get_validity(cert, &now, &thisUpdate, &nextUpdate);
-		fprintf(out, "  updates:   this %T\n",  &thisUpdate, utc);
-		fprintf(out, "             next %T, ", &nextUpdate, utc);
-		if (now > nextUpdate)
-		{
-			fprintf(out, "expired (%V ago)\n", &now, &nextUpdate);
-		}
-		else
-		{
-			fprintf(out, "ok");
-			if (now > nextUpdate - CRL_WARNING_INTERVAL * 60 * 60 * 24)
-			{
-				fprintf(out, " (expires in %V)", &now, &nextUpdate);
-			}
-			fprintf(out, " \n");
-		}
-
-		/* list optional authorityKeyIdentifier */
-		chunk = crl->get_authKeyIdentifier(crl);
-		if (chunk.ptr)
-		{
-			fprintf(out, "  authkey:   %#B\n", &chunk);
-		}
-	}
-	enumerator->destroy(enumerator);
-}
-
-/**
- * list all OCSP responses
- */
-static void stroke_list_ocsp(linked_list_t* list, bool utc, FILE *out)
-{
-	bool first = TRUE, ok;
-	enumerator_t *enumerator = list->create_enumerator(list);
-	certificate_t *cert;
-	time_t produced, usable, now = time(NULL);
-
-	while (enumerator->enumerate(enumerator, (void**)&cert))
-	{
-		if (first)
-		{
-			fprintf(out, "\n");
-			fprintf(out, "List of OCSP responses:\n");
-			fprintf(out, "\n");
-			first = FALSE;
-		}
-		fprintf(out, "  signer:   \"%Y\"\n", cert->get_issuer(cert));
-
-		/* check validity */
-		ok = cert->get_validity(cert, &now, &produced, &usable);
-		fprintf(out, "  validity:  produced at %T\n", &produced, utc);
-		fprintf(out, "             usable till %T, ", &usable, utc);
-		if (ok)
-		{
-			fprintf(out, "ok\n");
-		}
-		else
-		{
-			fprintf(out, "expired (%V ago)\n", &now, &usable);
-		}
-	}
-	enumerator->destroy(enumerator);
+	list->destroy_offset(list, offsetof(certificate_t, destroy));
 }
 
 /**
@@ -1439,19 +976,15 @@ METHOD(stroke_list_t, list, void,
 {
 	linked_list_t *cert_list = NULL;
 
+	cert_printer = certificate_printer_create(out, TRUE, msg->list.utc);
+
 	if (msg->list.flags & LIST_PUBKEYS)
 	{
-		linked_list_t *pubkey_list = create_unique_cert_list(CERT_TRUSTED_PUBKEY);
-
-		stroke_list_pubkeys(pubkey_list, msg->list.utc, out);
-		pubkey_list->destroy_offset(pubkey_list, offsetof(certificate_t, destroy));
+		stroke_list_other_certs(CERT_TRUSTED_PUBKEY);
 	}
 	if (msg->list.flags & LIST_CERTS)
 	{
-		linked_list_t *pgp_list = create_unique_cert_list(CERT_GPG);
-
-		stroke_list_pgp(pgp_list, msg->list.utc, out);
-		pgp_list->destroy_offset(pgp_list, offsetof(certificate_t, destroy));
+		stroke_list_other_certs(CERT_GPG);
 	}
 	if (msg->list.flags & (LIST_CERTS | LIST_CACERTS | LIST_OCSPCERTS | LIST_AACERTS))
 	{
@@ -1459,47 +992,33 @@ METHOD(stroke_list_t, list, void,
 	}
 	if (msg->list.flags & LIST_CERTS)
 	{
-		stroke_list_certs(cert_list, "X.509 End Entity Certificates",
-						  X509_NONE, msg->list.utc, out);
+		stroke_list_x509_certs(cert_list, X509_NONE);
 	}
 	if (msg->list.flags & LIST_CACERTS)
 	{
-		stroke_list_certs(cert_list, "X.509 CA Certificates",
-						  X509_CA, msg->list.utc, out);
+		stroke_list_x509_certs(cert_list, X509_CA);
 	}
 	if (msg->list.flags & LIST_OCSPCERTS)
 	{
-		stroke_list_certs(cert_list, "X.509 OCSP Signer Certificates",
-						  X509_OCSP_SIGNER, msg->list.utc, out);
+		stroke_list_x509_certs(cert_list, X509_OCSP_SIGNER);
 	}
 	if (msg->list.flags & LIST_AACERTS)
 	{
-		stroke_list_certs(cert_list, "X.509 AA Certificates",
-						  X509_AA, msg->list.utc, out);
+		stroke_list_x509_certs(cert_list, X509_AA);
 	}
 	DESTROY_OFFSET_IF(cert_list, offsetof(certificate_t, destroy));
 
 	if (msg->list.flags & LIST_ACERTS)
 	{
-		linked_list_t *ac_list = create_unique_cert_list(CERT_X509_AC);
-
-		stroke_list_acerts(ac_list, msg->list.utc, out);
-		ac_list->destroy_offset(ac_list, offsetof(certificate_t, destroy));
+		stroke_list_other_certs(CERT_X509_AC);
 	}
 	if (msg->list.flags & LIST_CRLS)
 	{
-		linked_list_t *crl_list = create_unique_cert_list(CERT_X509_CRL);
-
-		stroke_list_crls(crl_list, msg->list.utc, out);
-		crl_list->destroy_offset(crl_list, offsetof(certificate_t, destroy));
+		stroke_list_other_certs(CERT_X509_CRL);
 	}
 	if (msg->list.flags & LIST_OCSP)
 	{
-		linked_list_t *ocsp_list = create_unique_cert_list(CERT_X509_OCSP_RESPONSE);
-
-		stroke_list_ocsp(ocsp_list, msg->list.utc, out);
-
-		ocsp_list->destroy_offset(ocsp_list, offsetof(certificate_t, destroy));
+		stroke_list_other_certs(CERT_X509_OCSP_RESPONSE);
 	}
 	if (msg->list.flags & LIST_ALGS)
 	{
@@ -1509,6 +1028,8 @@ METHOD(stroke_list_t, list, void,
 	{
 		list_plugins(out);
 	}
+	cert_printer->destroy(cert_printer);
+	cert_printer = NULL;
 }
 
 /**
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
index 29563e3..ee32dbc 100644
--- a/src/libcharon/plugins/stroke/stroke_socket.c
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -590,17 +590,10 @@ static void stroke_loglevel(private_stroke_socket_t *this,
 		fprintf(out, "command not allowed!\n");
 		return;
 	}
-	if (strcaseeq(msg->loglevel.type, "any"))
+	if (!enum_from_name(debug_names, msg->loglevel.type, &group))
 	{
-		group = DBG_ANY;
-	}
-	else
-	{
-		if (!enum_from_name(debug_names, msg->loglevel.type, &group))
-		{
-			fprintf(out, "unknown type '%s'!\n", msg->loglevel.type);
-			return;
-		}
+		fprintf(out, "unknown type '%s'!\n", msg->loglevel.type);
+		return;
 	}
 	charon->set_level(charon, group, msg->loglevel.level);
 }
diff --git a/src/libcharon/plugins/systime_fix/Makefile.am b/src/libcharon/plugins/systime_fix/Makefile.am
index 40a3464..95a3323 100644
--- a/src/libcharon/plugins/systime_fix/Makefile.am
+++ b/src/libcharon/plugins/systime_fix/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 if MONOLITHIC
diff --git a/src/libcharon/plugins/systime_fix/Makefile.in b/src/libcharon/plugins/systime_fix/Makefile.in
index be148b6..0daff44 100644
--- a/src/libcharon/plugins/systime_fix/Makefile.in
+++ b/src/libcharon/plugins/systime_fix/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-systime-fix.la
diff --git a/src/libcharon/plugins/tnc_ifmap/Makefile.am b/src/libcharon/plugins/tnc_ifmap/Makefile.am
index 90fbf46..dab9812 100644
--- a/src/libcharon/plugins/tnc_ifmap/Makefile.am
+++ b/src/libcharon/plugins/tnc_ifmap/Makefile.am
@@ -1,7 +1,6 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
 	-I$(top_srcdir)/src/libtls \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/tnc_ifmap/Makefile.in b/src/libcharon/plugins/tnc_ifmap/Makefile.in
index 17cc341..f124a1b 100644
--- a/src/libcharon/plugins/tnc_ifmap/Makefile.in
+++ b/src/libcharon/plugins/tnc_ifmap/Makefile.in
@@ -419,6 +419,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -435,7 +437,6 @@ xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
 	-I$(top_srcdir)/src/libtls \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c
index d2ba2e3..2bad4fa 100644
--- a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c
+++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c
@@ -18,7 +18,6 @@
 #include "tnc_ifmap_renew_session_job.h"
 
 #include <daemon.h>
-#include <hydra.h>
 #include <utils/debug.h>
 
 #define IFMAP_RENEW_SESSION_INTERVAL	150
@@ -51,8 +50,8 @@ static bool publish_device_ip_addresses(private_tnc_ifmap_listener_t *this)
 	host_t *host;
 	bool success = TRUE;
 
-	enumerator = hydra->kernel_interface->create_address_enumerator(
-									hydra->kernel_interface, ADDR_TYPE_REGULAR);
+	enumerator = charon->kernel->create_address_enumerator(charon->kernel,
+														   ADDR_TYPE_REGULAR);
 	while (enumerator->enumerate(enumerator, &host))
 	{
 		if (!this->ifmap->publish_device_ip(this->ifmap, host))
diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.am b/src/libcharon/plugins/tnc_pdp/Makefile.am
index 3478c5b..fcda7d7 100644
--- a/src/libcharon/plugins/tnc_pdp/Makefile.am
+++ b/src/libcharon/plugins/tnc_pdp/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libradius \
 	-I$(top_srcdir)/src/libtncif \
diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.in b/src/libcharon/plugins/tnc_pdp/Makefile.in
index ef05275..bfd8cf8 100644
--- a/src/libcharon/plugins/tnc_pdp/Makefile.in
+++ b/src/libcharon/plugins/tnc_pdp/Makefile.in
@@ -420,6 +420,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -435,7 +437,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/libradius \
 	-I$(top_srcdir)/src/libtncif \
diff --git a/src/libcharon/plugins/uci/Makefile.am b/src/libcharon/plugins/uci/Makefile.am
index 134ced0..296c8db 100644
--- a/src/libcharon/plugins/uci/Makefile.am
+++ b/src/libcharon/plugins/uci/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/uci/Makefile.in b/src/libcharon/plugins/uci/Makefile.in
index 2c03138..a1c64ca 100644
--- a/src/libcharon/plugins/uci/Makefile.in
+++ b/src/libcharon/plugins/uci/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -429,7 +431,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/unity/Makefile.am b/src/libcharon/plugins/unity/Makefile.am
index 38923e0..1244cb3 100644
--- a/src/libcharon/plugins/unity/Makefile.am
+++ b/src/libcharon/plugins/unity/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/unity/Makefile.in b/src/libcharon/plugins/unity/Makefile.in
index 4f0a7e7..00bb149 100644
--- a/src/libcharon/plugins/unity/Makefile.in
+++ b/src/libcharon/plugins/unity/Makefile.in
@@ -415,6 +415,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -430,7 +432,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/updown/Makefile.am b/src/libcharon/plugins/updown/Makefile.am
index f03f474..f8738ad 100644
--- a/src/libcharon/plugins/updown/Makefile.am
+++ b/src/libcharon/plugins/updown/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/updown/Makefile.in b/src/libcharon/plugins/updown/Makefile.in
index 619d17a..863e144 100644
--- a/src/libcharon/plugins/updown/Makefile.in
+++ b/src/libcharon/plugins/updown/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/updown/updown_listener.c b/src/libcharon/plugins/updown/updown_listener.c
index 96282be..e51caab 100644
--- a/src/libcharon/plugins/updown/updown_listener.c
+++ b/src/libcharon/plugins/updown/updown_listener.c
@@ -1,7 +1,8 @@
 /*
  * Copyright (C) 2013 Tobias Brunner
  * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2016 Andreas Steffen
+ * HSR 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
@@ -21,7 +22,6 @@
 #include "updown_listener.h"
 
 #include <utils/process.h>
-#include <hydra.h>
 #include <daemon.h>
 #include <config/child_cfg.h>
 
@@ -205,25 +205,47 @@ static void push_vip_env(private_updown_listener_t *this, ike_sa_t *ike_sa,
 	enumerator->destroy(enumerator);
 }
 
+#define	PORT_BUF_LEN	12
+
 /**
  * Determine proper values for port env variable
  */
-static u_int16_t get_port(traffic_selector_t *me,
-						  traffic_selector_t *other, bool local)
+static char* get_port(traffic_selector_t *me, traffic_selector_t *other,
+					  char *port_buf, bool local)
 {
+	uint16_t port, to, from;
+
 	switch (max(me->get_protocol(me), other->get_protocol(other)))
 	{
 		case IPPROTO_ICMP:
 		case IPPROTO_ICMPV6:
 		{
-			u_int16_t port = me->get_from_port(me);
-
-			port = max(port, other->get_from_port(other));
-			return local ? traffic_selector_icmp_type(port)
-						 : traffic_selector_icmp_code(port);
+			port = max(me->get_from_port(me), other->get_from_port(other));
+			snprintf(port_buf, PORT_BUF_LEN, "%u",
+					 local ? traffic_selector_icmp_type(port)
+						   : traffic_selector_icmp_code(port));
+			return port_buf;
 		}
 	}
-	return local ? me->get_from_port(me) : other->get_from_port(other);
+	if (local)
+	{
+		from = me->get_from_port(me);
+		to   = me->get_to_port(me);
+	}
+	else
+	{
+		from = other->get_from_port(other);
+		to   = other->get_to_port(other);
+	}
+	if (from == to || (from == 0 && to == 65535))
+	{
+		snprintf(port_buf, PORT_BUF_LEN, "%u", from);
+	}
+	else
+	{
+		snprintf(port_buf, PORT_BUF_LEN, "%u:%u", from, to);
+	}
+	return port_buf;
 }
 
 /**
@@ -241,6 +263,7 @@ static void invoke_once(private_updown_listener_t *this, ike_sa_t *ike_sa,
 	int out;
 	FILE *shell;
 	process_t *process;
+	char port_buf[PORT_BUF_LEN];
 	char *envp[128] = {};
 
 	me = ike_sa->get_my_host(ike_sa);
@@ -265,8 +288,7 @@ static void invoke_once(private_updown_listener_t *this, ike_sa_t *ike_sa,
 			 config->get_name(config));
 	if (up)
 	{
-		if (hydra->kernel_interface->get_interface(hydra->kernel_interface,
-												   me, &iface))
+		if (charon->kernel->get_interface(charon->kernel, me, &iface))
 		{
 			cache_iface(this, child_sa->get_reqid(child_sa), iface);
 		}
@@ -289,25 +311,29 @@ static void invoke_once(private_updown_listener_t *this, ike_sa_t *ike_sa,
 			 ike_sa->get_unique_id(ike_sa));
 	push_env(envp, countof(envp), "PLUTO_ME=%H", me);
 	push_env(envp, countof(envp), "PLUTO_MY_ID=%Y", ike_sa->get_my_id(ike_sa));
-	if (my_ts->to_subnet(my_ts, &host, &mask))
+	if (!my_ts->to_subnet(my_ts, &host, &mask))
 	{
-		push_env(envp, countof(envp), "PLUTO_MY_CLIENT=%+H/%u", host, mask);
-		host->destroy(host);
+		DBG1(DBG_CHD, "updown approximates local TS %R "
+					  "by next larger subnet", my_ts);
 	}
-	push_env(envp, countof(envp), "PLUTO_MY_PORT=%u",
-			 get_port(my_ts, other_ts, TRUE));
+	push_env(envp, countof(envp), "PLUTO_MY_CLIENT=%+H/%u", host, mask);
+	host->destroy(host);
+	push_env(envp, countof(envp), "PLUTO_MY_PORT=%s",
+			 get_port(my_ts, other_ts, port_buf, TRUE));
 	push_env(envp, countof(envp), "PLUTO_MY_PROTOCOL=%u",
 			 my_ts->get_protocol(my_ts));
 	push_env(envp, countof(envp), "PLUTO_PEER=%H", other);
 	push_env(envp, countof(envp), "PLUTO_PEER_ID=%Y",
 			 ike_sa->get_other_id(ike_sa));
-	if (other_ts->to_subnet(other_ts, &host, &mask))
+	if (!other_ts->to_subnet(other_ts, &host, &mask))
 	{
-		push_env(envp, countof(envp), "PLUTO_PEER_CLIENT=%+H/%u", host, mask);
-		host->destroy(host);
+		DBG1(DBG_CHD, "updown approximates remote TS %R "
+					  "by next larger subnet", other_ts);
 	}
-	push_env(envp, countof(envp), "PLUTO_PEER_PORT=%u",
-			 get_port(my_ts, other_ts, FALSE));
+	push_env(envp, countof(envp), "PLUTO_PEER_CLIENT=%+H/%u", host, mask);
+	host->destroy(host);
+	push_env(envp, countof(envp), "PLUTO_PEER_PORT=%s",
+			 get_port(my_ts, other_ts, port_buf, FALSE));
 	push_env(envp, countof(envp), "PLUTO_PEER_PROTOCOL=%u",
 			 other_ts->get_protocol(other_ts));
 	if (ike_sa->has_condition(ike_sa, COND_EAP_AUTHENTICATED) ||
diff --git a/src/libcharon/plugins/vici/Makefile.am b/src/libcharon/plugins/vici/Makefile.am
index c99d23e..ca9b499 100644
--- a/src/libcharon/plugins/vici/Makefile.am
+++ b/src/libcharon/plugins/vici/Makefile.am
@@ -1,6 +1,6 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
+	-I$(top_srcdir)/src/libstrongswan/plugins/pubkey \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
@@ -18,6 +18,7 @@ libstrongswan_vici_la_SOURCES = \
 	vici_message.h vici_message.c \
 	vici_builder.h vici_builder.c \
 	vici_dispatcher.h vici_dispatcher.c \
+	vici_cert_info.h vici_cert_info.c \
 	vici_query.h vici_query.c \
 	vici_control.h vici_control.c \
 	vici_config.h vici_config.c \
@@ -38,6 +39,7 @@ ipseclib_LTLIBRARIES = libvici.la
 libvici_la_SOURCES = \
 	vici_message.c vici_message.h \
 	vici_builder.c vici_builder.h \
+	vici_cert_info.h vici_cert_info.c \
 	libvici.c libvici.h
 
 libvici_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
@@ -79,3 +81,7 @@ endif
 if USE_PYTHON_EGGS
 SUBDIRS += python
 endif
+
+if USE_PERL_CPAN
+SUBDIRS += perl
+endif
diff --git a/src/libcharon/plugins/vici/Makefile.in b/src/libcharon/plugins/vici/Makefile.in
index 1a7870a..86ed007 100644
--- a/src/libcharon/plugins/vici/Makefile.in
+++ b/src/libcharon/plugins/vici/Makefile.in
@@ -82,6 +82,7 @@ TESTS = vici_tests$(EXEEXT)
 check_PROGRAMS = $(am__EXEEXT_1)
 @USE_RUBY_GEMS_TRUE at am__append_1 = ruby
 @USE_PYTHON_EGGS_TRUE at am__append_2 = python
+ at USE_PERL_CPAN_TRUE@am__append_3 = perl
 subdir = src/libcharon/plugins/vici
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/depcomp
@@ -134,9 +135,10 @@ LTLIBRARIES = $(ipseclib_LTLIBRARIES) $(noinst_LTLIBRARIES) \
 	$(plugin_LTLIBRARIES)
 libstrongswan_vici_la_LIBADD =
 am_libstrongswan_vici_la_OBJECTS = vici_socket.lo vici_message.lo \
-	vici_builder.lo vici_dispatcher.lo vici_query.lo \
-	vici_control.lo vici_config.lo vici_cred.lo vici_attribute.lo \
-	vici_authority.lo vici_logger.lo vici_plugin.lo
+	vici_builder.lo vici_dispatcher.lo vici_cert_info.lo \
+	vici_query.lo vici_control.lo vici_config.lo vici_cred.lo \
+	vici_attribute.lo vici_authority.lo vici_logger.lo \
+	vici_plugin.lo
 libstrongswan_vici_la_OBJECTS = $(am_libstrongswan_vici_la_OBJECTS)
 AM_V_lt = $(am__v_lt_ at AM_V@)
 am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
@@ -150,7 +152,8 @@ libstrongswan_vici_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 @MONOLITHIC_TRUE at am_libstrongswan_vici_la_rpath =
 libvici_la_DEPENDENCIES =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la
-am_libvici_la_OBJECTS = vici_message.lo vici_builder.lo libvici.lo
+am_libvici_la_OBJECTS = vici_message.lo vici_builder.lo \
+	vici_cert_info.lo libvici.lo
 libvici_la_OBJECTS = $(am_libvici_la_OBJECTS)
 am__EXEEXT_1 = vici_tests$(EXEEXT)
 am__dirstamp = $(am__leading_dot)dirstamp
@@ -270,7 +273,7 @@ am__tty_colors = { \
     std=''; \
   fi; \
 }
-DIST_SUBDIRS = ruby python
+DIST_SUBDIRS = ruby python perl
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 am__relativize = \
   dir0=`pwd`; \
@@ -509,6 +512,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -524,7 +529,7 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
+	-I$(top_srcdir)/src/libstrongswan/plugins/pubkey \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
@@ -538,6 +543,7 @@ libstrongswan_vici_la_SOURCES = \
 	vici_message.h vici_message.c \
 	vici_builder.h vici_builder.c \
 	vici_dispatcher.h vici_dispatcher.c \
+	vici_cert_info.h vici_cert_info.c \
 	vici_query.h vici_query.c \
 	vici_control.h vici_control.c \
 	vici_config.h vici_config.c \
@@ -553,6 +559,7 @@ ipseclib_LTLIBRARIES = libvici.la
 libvici_la_SOURCES = \
 	vici_message.c vici_message.h \
 	vici_builder.c vici_builder.h \
+	vici_cert_info.h vici_cert_info.c \
 	libvici.c libvici.h
 
 libvici_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
@@ -578,7 +585,7 @@ vici_tests_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
 	$(top_builddir)/src/libstrongswan/tests/libtest.la
 
-SUBDIRS = $(am__append_1) $(am__append_2)
+SUBDIRS = $(am__append_1) $(am__append_2) $(am__append_3)
 all: all-recursive
 
 .SUFFIXES:
@@ -739,6 +746,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_attribute.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_authority.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_builder.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_cert_info.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_config.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_control.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_cred.Plo at am__quote@
diff --git a/src/libcharon/plugins/vici/README.md b/src/libcharon/plugins/vici/README.md
index b9531d8..52929bd 100644
--- a/src/libcharon/plugins/vici/README.md
+++ b/src/libcharon/plugins/vici/README.md
@@ -258,7 +258,8 @@ Initiates an SA while streaming _control-log_ events.
 
 	{
 		child = <CHILD_SA configuration name to initiate>
-		timeout = <timeout in seconds before returning>
+		ike = <optional IKE_SA configuraiton name to find child under>
+		timeout = <timeout in ms before returning>
 		init-limits = <whether limits may prevent initiating the CHILD_SA>
 		loglevel = <loglevel to issue "control-log" events for>
 	} => {
@@ -266,6 +267,9 @@ Initiates an SA while streaming _control-log_ events.
 		errmsg = <error string on failure or timeout>
 	}
 
+The default timeout of 0 waits indefinitely for a result, and a timeout value
+of -1 returns a result immediately.
+
 ### terminate() ###
 
 Terminates an SA while streaming _control-log_ events.
@@ -275,19 +279,40 @@ Terminates an SA while streaming _control-log_ events.
 		ike = <terminate an IKE_SA by configuration name>
 		child_id = <terminate a CHILD_SA by its reqid>
 		ike_id = <terminate an IKE_SA by its unique id>
-		timeout = <timeout in seconds before returning>
+		timeout = <timeout in ms before returning>
 		loglevel = <loglevel to issue "control-log" events for>
 	} => {
 		success = <yes or no>
 		errmsg = <error string on failure or timeout>
 	}
 
+The default timeout of 0 waits indefinitely for a result, and a timeout value
+of -1 returns a result immediately.
+
+### redirect() ###
+
+Redirect a client-initiated IKE_SA to another gateway.  Only for IKEv2 and if
+supported by the peer.
+
+	{
+		ike = <redirect an IKE_SA by configuration name>
+		ike-id = <redirect an IKE_SA by its unique id>
+		peer-ip = <redirect an IKE_SA with matching peer IP, may also be a
+				   subnet in CIDR notation or an IP range>
+		peer-id = <redirect an IKE_SA with matching peer identity, may contain
+				   wildcards>
+	} => {
+		success = <yes or no>
+		errmsg = <error string on failure>
+	}
+
 ### install() ###
 
 Install a trap, drop or bypass policy defined by a CHILD_SA config.
 
 	{
 		child = <CHILD_SA configuration name to install>
+		ike = <optional IKE_SA configuraiton name to find child under>
 	} => {
 		success = <yes or no>
 		errmsg = <error string on failure>
@@ -361,7 +386,9 @@ call includes all certificates known by the daemon, not only those loaded
 over vici.
 
 	{
-		type = <certificate type to filter for, or ANY>
+		type = <certificate type to filter for, X509|X509_AC|X509_CRL|
+												OCSP_RESPONSE|PUBKEY  or ANY>
+		flag = <X.509 certificate flag to filter for, NONE|CA|AA|OCSP or ANY>
 		subject = <set to list only certificates having subject>
 	} => {
 		# completes after streaming list-cert events
@@ -419,7 +446,8 @@ Unload a previously loaded connection definition by name.
 Load a certificate into the daemon.
 
 	{
-		type = <certificate type, X509|X509CA|X509AA|X509CRL|X509AC>
+		type = <certificate type, X509|X509_AC|X509_CRL>
+		flag = <X.509 certificate flag, NONE|CA|AA|OCSP>
 		data = <PEM or DER encoded certificate data>
 	} => {
 		success = <yes or no>
@@ -544,6 +572,16 @@ List the currently loaded pools.
 		}
 	}
 
+### get-algorithms() ###
+
+List currently loaded algorithms and their implementation.
+
+	{} => {
+		<algorithm type> = {
+			<algorithm> = <plugin providing the implementation>
+		}
+	}
+
 ## Server-issued events ##
 
 Based on the packet layer, the vici plugin raises event messages using named
@@ -588,8 +626,10 @@ command.
 			version = <IKE version, 1 or 2>
 			state = <IKE_SA state name>
 			local-host = <local IKE endpoint address>
+			local-port = <local IKE endpoint port>
 			local-id = <local IKE identity>
 			remote-host = <remote IKE endpoint address>
+			remote-port = <remote IKE endpoint port>
 			remote-id = <remote IKE identity>
 			remote-xauth-id = <remote XAuth identity, if XAuth-authenticated>
 			remote-eap-id = <remote EAP identity, if EAP-authenticated>
@@ -735,9 +775,13 @@ The _list-cert_ event is issued to stream loaded certificates during an active
 _list-certs_ command.
 
 	{
-		type = <certificate type>
+		type = <certificate type, X509|X509_AC|X509_CRL|OCSP_RESPONSE|PUBKEY>
+		flag = <X.509 certificate flag, NONE|CA|AA|OCSP>
 		has_privkey = <set if a private key for the certificate is available>
 		data = <ASN1 encoded certificate data>
+		subject = <subject string if defined and certificate type is PUBKEY>
+		not-before = <time string if defined and certificate type is PUBKEY>
+		not-after  = <time string if defined and certificate type is PUBKEY>
 	}
 
 ### list-authority ###
@@ -763,7 +807,7 @@ information during an active_list-authorities_ command.
 The _ike-updown_ event is issued when an IKE_SA is established or terminated.
 
 	{
-		up = <yes or no>
+		up = <set if up event>
 		<IKE_SA config name> = {
 			<same data as in the list-sas event, but without child-sas section>
 		}
@@ -789,7 +833,7 @@ The _ike-rekey_ event is issued when an IKE_SA is rekeyed.
 The _child-updown_ event is issued when a CHILD_SA is established or terminated.
 
 	{
-		up = <yes or no>
+		up = <set if up event>
 		<IKE_SA config name> = {
 			<same data as in the list-sas event, but with only the affected
 			 CHILD_SA in the child-sas section>
@@ -1068,3 +1112,43 @@ dictionaries. Objects returned by the library use OrderedDicts.
 
 For more details about the Python egg refer to the comments in the Python source
 code.
+
+# Vici::Session Perl CPAN module #
+
+The _Vici::Session Perl CPAN module_ is a pure Perl implementation of the VICI
+protocol to implement client applications. It is provided in the _perl_
+subdirectory, and gets built and installed if strongSwan has been
+ _./configure_'d with_--enable-vici_ and _--enable-perl-cpan_.
+
+The _Vici::Session_ module provides a _new()_ constructor for a high level
+interface, the underlying _Vici::Packet_ and _Vici::Transport_ classes are
+usually not required to build Perl applications using VICI. The _Vici::Session_
+class provides methods for the supported VICI commands. The auxiliare
+ _Vici::Message_ class is used to encode configuration parameters sent to
+the daemon and decode data returned by the daemon.
+
+## Connecting to the daemon ##
+
+	use IO::Socket::UNIX;
+	use Vici::Session;
+	use Vici::Message;
+
+	my $socket = IO::Socket::UNIX->new(
+			Type => SOCK_STREAM,
+			Peer => '/var/run/charon.vici',
+	) or die "Vici socket: $!";
+
+	my $session = Vici::Session->new($socket);
+
+## A simple client request ##
+
+An example to print the daemon version information is as simple as:
+
+	my $version = $session->version()->hash();
+
+	foreach my $key ('daemon', 'version', 'sysname', 'release', 'machine' ) {
+		print $version->{$key}, " ";
+	}
+
+The _Vici::Session_ methods are explained in the perl/Vici-Session/README.pod
+document.
diff --git a/src/libcharon/plugins/vici/perl/Makefile.am b/src/libcharon/plugins/vici/perl/Makefile.am
new file mode 100644
index 0000000..9bc6262
--- /dev/null
+++ b/src/libcharon/plugins/vici/perl/Makefile.am
@@ -0,0 +1,27 @@
+EXTRA_DIST = \
+	Vici-Session/Changes \
+	Vici-Session/Makefile.PL \
+	Vici-Session/MANIFEST \
+	Vici-Session/README.pod \
+	Vici-Session/t/Vici-Session.t \
+	Vici-Session/lib/Vici/Message.pm \
+	Vici-Session/lib/Vici/Packet.pm \
+	Vici-Session/lib/Vici/Session.pm \
+	Vici-Session/lib/Vici/Transport.pm
+
+all-local: Vici-Session/pm_to_blib
+
+Vici-Session/Makefile: $(srcdir)/Vici-Session/Makefile.PL
+	(cd $(srcdir)/Vici-Session; $(PERL) Makefile.PL)
+
+Vici-Session/pm_to_blib: $(EXTRA_DIST) $(srcdir)/Vici-Session/Makefile
+	(cd $(srcdir)/Vici-Session; make)
+
+clean-local:
+	(cd $(srcdir)/Vici-Session; [ ! -f Makefile ] || make clean)
+
+if PERL_CPAN_INSTALL
+install-exec-local: Vici-Session/pm_to_blib
+	(cd $(srcdir)/Vici-Session; make install)
+endif
+
diff --git a/src/libcharon/plugins/vici/perl/Makefile.in b/src/libcharon/plugins/vici/perl/Makefile.in
new file mode 100644
index 0000000..550d3e9
--- /dev/null
+++ b/src/libcharon/plugins/vici/perl/Makefile.in
@@ -0,0 +1,567 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 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.
+
+ at SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@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/libcharon/plugins/vici/perl
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+	$(top_srcdir)/m4/config/ltoptions.m4 \
+	$(top_srcdir)/m4/config/ltsugar.m4 \
+	$(top_srcdir)/m4/config/ltversion.m4 \
+	$(top_srcdir)/m4/config/lt~obsolete.m4 \
+	$(top_srcdir)/m4/macros/split-package-version.m4 \
+	$(top_srcdir)/m4/macros/with.m4 \
+	$(top_srcdir)/m4/macros/enable-disable.m4 \
+	$(top_srcdir)/m4/macros/add-plugin.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GEM = @GEM@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
+PTHREADLIB = @PTHREADLIB@
+PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+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_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+EXTRA_DIST = \
+	Vici-Session/Changes \
+	Vici-Session/Makefile.PL \
+	Vici-Session/MANIFEST \
+	Vici-Session/README.pod \
+	Vici-Session/t/Vici-Session.t \
+	Vici-Session/lib/Vici/Message.pm \
+	Vici-Session/lib/Vici/Packet.pm \
+	Vici-Session/lib/Vici/Session.pm \
+	Vici-Session/lib/Vici/Transport.pm
+
+all: all-am
+
+.SUFFIXES:
+$(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 ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/vici/perl/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/libcharon/plugins/vici/perl/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
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+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 "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$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 all-local
+installdirs:
+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:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+ at PERL_CPAN_INSTALL_FALSE@install-exec-local:
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-local mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-exec-local
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am all-local check check-am clean clean-generic \
+	clean-libtool clean-local cscopelist-am ctags-am distclean \
+	distclean-generic distclean-libtool 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-exec-local install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags-am uninstall uninstall-am
+
+
+all-local: Vici-Session/pm_to_blib
+
+Vici-Session/Makefile: $(srcdir)/Vici-Session/Makefile.PL
+	(cd $(srcdir)/Vici-Session; $(PERL) Makefile.PL)
+
+Vici-Session/pm_to_blib: $(EXTRA_DIST) $(srcdir)/Vici-Session/Makefile
+	(cd $(srcdir)/Vici-Session; make)
+
+clean-local:
+	(cd $(srcdir)/Vici-Session; [ ! -f Makefile ] || make clean)
+
+ at PERL_CPAN_INSTALL_TRUE@install-exec-local: Vici-Session/pm_to_blib
+ at PERL_CPAN_INSTALL_TRUE@	(cd $(srcdir)/Vici-Session; make install)
+
+# 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/libcharon/plugins/vici/perl/Vici-Session/Changes b/src/libcharon/plugins/vici/perl/Vici-Session/Changes
new file mode 100644
index 0000000..0c30328
--- /dev/null
+++ b/src/libcharon/plugins/vici/perl/Vici-Session/Changes
@@ -0,0 +1,6 @@
+Revision history for Perl extension Vici::Session.
+
+0.9  Tue Nov 17 11:45:21 2015
+	- original version; created by h2xs 1.23 with options
+		-X -n Vici::Session
+
diff --git a/src/libcharon/plugins/vici/perl/Vici-Session/MANIFEST b/src/libcharon/plugins/vici/perl/Vici-Session/MANIFEST
new file mode 100644
index 0000000..c19032a
--- /dev/null
+++ b/src/libcharon/plugins/vici/perl/Vici-Session/MANIFEST
@@ -0,0 +1,9 @@
+Changes
+Makefile.PL
+MANIFEST
+README.pod
+t/Vici-Session.t
+lib/Vici/Session.pm
+lib/Vici/Message.pm
+lib/Vici/Packet.pm
+lib/Vici/Transport.pm
diff --git a/src/libcharon/plugins/vici/perl/Vici-Session/Makefile.PL b/src/libcharon/plugins/vici/perl/Vici-Session/Makefile.PL
new file mode 100644
index 0000000..65f4945
--- /dev/null
+++ b/src/libcharon/plugins/vici/perl/Vici-Session/Makefile.PL
@@ -0,0 +1,11 @@
+use ExtUtils::MakeMaker;
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+WriteMakefile(
+    NAME              => 'Vici::Session',
+    VERSION_FROM      => 'lib/Vici/Session.pm', # finds $VERSION
+    PREREQ_PM         => {}, # e.g., Module::Name => 1.1
+    ($] >= 5.005 ?     ## Add these new keywords supported since 5.005
+      (ABSTRACT_FROM  => 'lib/Vici/Session.pm', # retrieve abstract from module
+       AUTHOR         => 'Andreas Steffen <andreas.steffen@>strongswan.org') : ()),
+);
diff --git a/src/libcharon/plugins/vici/perl/Vici-Session/README.pod b/src/libcharon/plugins/vici/perl/Vici-Session/README.pod
new file mode 100644
index 0000000..de374aa
--- /dev/null
+++ b/src/libcharon/plugins/vici/perl/Vici-Session/README.pod
@@ -0,0 +1,649 @@
+
+=head1 NAME
+
+Vici::Session - Perl binding for the strongSwan VICI configuration interface
+
+=head1 DESCRIPTION
+
+The Vici::Session module allows a Perl script to communicate with the open
+source strongSwan IPsec daemon (https://www.strongswan.org) via the documented
+Versatile IKE Configuration Interface (VICI). VICI allows the configuration,
+management and monitoring of multiple IPsec connections.
+
+=head1 INSTALLATION
+
+To install this module type the following:
+
+  perl Makefile.PL
+  make
+  make install
+
+=head1 DEPENDENCIES
+
+This module requires the standard networking module:
+
+  IO::Socket::UNIX
+
+=head1 METHODS
+
+The following examples show the use of the Vici::Session interface in a
+a "net-net" connection between the VPN gateways "moon" and "sun".
+
+=cut
+
+use strict;
+use warnings;
+use IO::Socket::UNIX;
+use Vici::Message;
+use Vici::Session;
+
+my $moon_key = "-----BEGIN RSA PRIVATE KEY-----\n" .
+    "MIIEowIBAAKCAQEApHwF+sUXQdH+WwYzdPMzpjuwhGGvHgsmBah1IQsPsddL9gZy" .
+    "gerzpTM1vvQ4kbRuvE3SZWLf9uKEbiQV9IABr87L9JAva56EHIAiUMuG8WizVbIK" .
+    "IhQlZc8S2mIwAW0Jc6EmnoJv9j6F/tVD9+6xvMJbwHLi0h7BUO9tBVLPy72YeGNB" .
+    "Y6Cob4CrOuFOJyACezJ7i9vZ+XzOfnXpu7qL0DgYP/n2maPEJGEivTFunkJD/mJ8" .
+    "DecyLTQcchsCj2118BMuf2qjVn4UWPCBBuhyYK5wsATB1ANeAtlFfgH+wsuHjZwt" .
+    "TJru05lGHBZ3F2hZ9PO68hVHbIZZj6SB8X47nwIDAQABAoIBAAQDXqX6rxGVDQ6t" .
+    "fQ3qbSUuKaVhOMOT5A6ZSJpQycY+CYVsLNkMoXszX6lUDhlH/Letcme03OAKMM77" .
+    "JGn9wYzHj+RcrDuE95Y2bh/oh1dWhaGeoW6pbSwpvD0FzkQKpANlOCr/5bltVxmb" .
+    "nHftI/sGBvUQGIal53ORE+jgV1+SK6I0oAIWiCpU2oZpYMAtp7WxOngsAJaGtk//" .
+    "m2ckH+T8uVHwe9gJ9HZnEk+Io6BXScMNNrsbd2J+pQ75wQXfzHEzHAj+ElhWzhtc" .
+    "5XefqHw/DfpPDX/lby3VoSoagqzsVuUx7LylgzIDxTsb9HQVOLjDzOQ+vn22Xj7g" .
+    "UCEjwLkCgYEA2EZguuzJdxRIWBSnIyzpCzfqm0EgybpeLuJVfzWla0yKWI6AeLhW" .
+    "cr+7o9UE8nCQHVffIrgjWksjc/S5FhzC9TYSHpPa8TPgebTQK4VxnP9Qkh/XRpJj" .
+    "CqgJ8k2MYleHYxa+AKQv/25yNhLdowkNR0iU1kbiaYRJMP0WigAmdAUCgYEAwrJe" .
+    "Y3LAawOkalJFMFTtLXsqZE91TFwMt9TQnzysGH3Q6+9N+qypS5KCes650+qgrwBV" .
+    "RmRNc1ixylToP3B0BKY5OD/BwMx1L/zSO3x7I4ZDasCu33y2ukGLcVSxrxTPTGdd" .
+    "8fhEiVO1CDXcM08/kSeQa049J8ziY3M+4NDchlMCgYEAw2VCO1923Tjb64gtQOBw" .
+    "ZAxOz5nVz6urL9yYted33is2yq9kbqzMnbuQAYKRh6Ae9APRuwJ2HjvIehjdp5aw" .
+    "pO4HDM00f7sI0ayEbu2PKfKZjotp6X6UMKqE4f8iGC9QSDvhyZ6NJs9YLHZ6+7NP" .
+    "5dkzbyx3njFAFxxxYpikJSkCgYByShB8YlUvvKCcRRUWbRQZWa6l2brqizJwCz43" .
+    "636+lcS5au2klAyBL0zm2Elfa+DNOe3U93Y7mrorIrJ+4v1H6We3bD3JdnvoIooq" .
+    "n0UNsngKx3cf++6r4WQAsA3pz9ZsbFVKgEmDL58aZbuQZxnSlJ4DT5c4sN3IMVOc" .
+    "1x5MvwKBgHudAaLvioIopBpYzOsK2OtEn6NQ7SwH0BLEUulHysaHqan5oExmM1bm" .
+    "YeivMDc9hj0YLXA47ryQHTx4vB5Nv3TI/LoUG6VrCvZvocQOXe/n7TguwAjJj7ef" .
+    "E55Gy8lXDRENyJMP1vif3N2iH8eQ1ASf8k/+gnBNkjSlYSSQUDfV\n" .
+    "-----END RSA PRIVATE KEY-----\n";
+ 
+my $moon_cert = "-----BEGIN CERTIFICATE-----\n" .
+    "MIIEIjCCAwqgAwIBAgIBKzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJDSDEZ" .
+    "MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBS" .
+    "b290IENBMB4XDTE0MDgyNzE0NDQ1NloXDTE5MDgyNjE0NDQ1NlowRjELMAkGA1UE" .
+    "BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xHDAaBgNVBAMTE21vb24u" .
+    "c3Ryb25nc3dhbi5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCk" .
+    "fAX6xRdB0f5bBjN08zOmO7CEYa8eCyYFqHUhCw+x10v2BnKB6vOlMzW+9DiRtG68" .
+    "TdJlYt/24oRuJBX0gAGvzsv0kC9rnoQcgCJQy4bxaLNVsgoiFCVlzxLaYjABbQlz" .
+    "oSaegm/2PoX+1UP37rG8wlvAcuLSHsFQ720FUs/LvZh4Y0FjoKhvgKs64U4nIAJ7" .
+    "MnuL29n5fM5+dem7uovQOBg/+faZo8QkYSK9MW6eQkP+YnwN5zItNBxyGwKPbXXw" .
+    "Ey5/aqNWfhRY8IEG6HJgrnCwBMHUA14C2UV+Af7Cy4eNnC1Mmu7TmUYcFncXaFn0" .
+    "87ryFUdshlmPpIHxfjufAgMBAAGjggEaMIIBFjAJBgNVHRMEAjAAMAsGA1UdDwQE" .
+    "AwIDqDAdBgNVHQ4EFgQU2CY9Iex8275aOQxbcMsDgCHerhMwbQYDVR0jBGYwZIAU" .
+    "XafdcAZRMn7ntm2zteXgYOouTe+hSaRHMEUxCzAJBgNVBAYTAkNIMRkwFwYDVQQK" .
+    "ExBMaW51eCBzdHJvbmdTd2FuMRswGQYDVQQDExJzdHJvbmdTd2FuIFJvb3QgQ0GC" .
+    "AQAwHgYDVR0RBBcwFYITbW9vbi5zdHJvbmdzd2FuLm9yZzATBgNVHSUEDDAKBggr" .
+    "BgEFBQcDATA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vY3JsLnN0cm9uZ3N3YW4u" .
+    "b3JnL3N0cm9uZ3N3YW4uY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQCpnj6Nc+PuPLPi" .
+    "4E3g5hyJkr5VZy7SSglcs1uyVP2mfwj6JR9SLd5+JOsL1aCTm0y9qLcqdbHBxG8i" .
+    "LNLtwVKU3s1hV4EIO3saHe4XUEjxN9bDtLWEoeq5ipmYX8RJ/fXKR8/8vurBARP2" .
+    "xu1+wqwEhymp4jBmF0LVovT1+o+GhH66zIJnx3zR9BtfMkaeL6804hrx2ygeopeo" .
+    "buGvMDQ8HcnMB9OU7Y8fK0oY1kULl6hf36K5ApPA6766sRRKRvBSKlmViKSQTq5a" .
+    "4c8gCWAZbtdT+N/fa8hKDlZt5q10EgjTqDfGTj50xKvAneq7XdfKmYYGnIWoNLY9" .
+    "ga8NOzX8\n" .
+    "-----END CERTIFICATE-----\n";
+
+my $ca_cert = "-----BEGIN CERTIFICATE-----\n" .
+    "MIIDuDCCAqCgAwIBAgIBADANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJDSDEZ" .
+    "MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBS" .
+    "b290IENBMB4XDTA0MDkxMDEwMDExOFoXDTE5MDkwNzEwMDExOFowRTELMAkGA1UE" .
+    "BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9u" .
+    "Z1N3YW4gUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL/y" .
+    "X2LqPVZuWLPIeknK86xhz6ljd3NNhC2z+P1uoCP3sBMuZiZQEjFzhnKcbXxCeo2f" .
+    "FnvhOOjrrisSuVkzuu82oxXD3fIkzuS7m9V4E10EZzgmKWIf+WuNRfbgAuUINmLc" .
+    "4YGAXBQLPyzpP4Ou48hhz/YQo58Bics6PHy5v34qCVROIXDvqhj91P8g+pS+F21/" .
+    "7P+CH2jRcVIEHZtG8M/PweTPQ95dPzpYd2Ov6SZ/U7EWmbMmT8VcUYn1aChxFmy5" .
+    "gweVBWlkH6MP+1DeE0/tL5c87xo5KCeGK8Tdqpe7sBRC4pPEEHDQciTUvkeuJ1Pr" .
+    "K+1LwdqRxo7HgMRiDw8CAwEAAaOBsjCBrzASBgNVHRMBAf8ECDAGAQH/AgEBMAsG" .
+    "A1UdDwQEAwIBBjAdBgNVHQ4EFgQUXafdcAZRMn7ntm2zteXgYOouTe8wbQYDVR0j" .
+    "BGYwZIAUXafdcAZRMn7ntm2zteXgYOouTe+hSaRHMEUxCzAJBgNVBAYTAkNIMRkw" .
+    "FwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRswGQYDVQQDExJzdHJvbmdTd2FuIFJv" .
+    "b3QgQ0GCAQAwDQYJKoZIhvcNAQELBQADggEBACOSmqEBtBLR9aV3UyCI8gmzR5in" .
+    "Lte9aUXXS+qis6F2h2Stf4sN+Nl6Gj7REC6SpfEH4wWdwiUL5J0CJhyoOjQuDl3n" .
+    "1Dw3dE4/zqMZdyDKEYTU75TmvusNJBdGsLkrf7EATAjoi/nrTOYPPhSUZvPp/D+Y" .
+    "vORJ9Ej51GXlK1nwEB5iA8+tDYniNQn6BD1MEgIejzK+fbiy7braZB1kqhoEr2Si" .
+    "7luBSnU912sw494E88a2EWbmMvg2TVHPNzCpVkpNk7kifCiwmw9VldkqYy9y/lCa" .
+    "Epyp7lTfKw7cbD04Vk8QJW782L6Csuxkl346b17wmOqn8AZips3tFsuAY3w=\n" .
+    "-----END CERTIFICATE-----\n" ;
+
+=pod
+
+The VICI interface requires a UNIX socket in order to communicate with the
+strongSwan charon daemon:
+
+  use IO::Socket::UNIX;
+
+  my $socket = IO::Socket::UNIX->new(
+          Type => SOCK_STREAM,
+          Peer => '/var/run/charon.vici',
+  ) or die "Vici socket: $!";
+
+=cut
+
+my $socket = IO::Socket::UNIX->new(
+            Type => SOCK_STREAM,
+            Peer => '/var/run/charon.vici',
+) or die "Vici socket: $!";
+
+=over
+
+=item new()
+
+creates a new Vici::Session object.
+
+  use Vici::Session;
+  use Vici::Message;
+
+  my $session = Vici::Session->new($socket);
+
+=cut
+
+my $session = Vici::Session->new($socket);
+
+=item version()
+
+returns daemon and system specific version information.
+
+  my $version = $session->version();
+
+=cut
+
+print "----- version -----\n";
+my $version = $session->version();
+print $version->raw(), "\n";
+
+=item load_cert()
+
+loads a certificate into the daemon.
+
+  my %vars = ( type => 'X509', flag => 'CA', data => $ca_cert );
+  my ($res, $errmsg) = $session->load_cert(Vici::Message->new(\%vars));
+
+=cut
+
+print "----- load-cert -----\n";
+my %vars = ( type => 'X509', flag => 'CA', data => $ca_cert );
+my ($res, $errmsg) = $session->load_cert(Vici::Message->new(\%vars));
+print $res ? "ok\n" : "failed: $errmsg\n";
+
+=item load_key()
+
+loads a private key into the daemon.
+
+  my %vars = ( type => 'RSA', data => $moon_key );
+  my ($res, $errmsg) = $session->load_key(Vici::Message->new(\%vars));
+
+=cut
+
+print "----- load-key -----\n";
+%vars = ( type => 'RSA', data => $moon_key );
+($res, $errmsg) = $session->load_key(Vici::Message->new(\%vars));
+print $res ? "ok\n" : "failed: $errmsg\n";
+
+=item load_shared()
+
+loads a shared IKE PSK, EAP or XAuth secret into the daemon.
+
+  my @owners = ( 'carol' );
+  my %vars = ( type => 'EAP', data => 'Ar3etTnp', owners => \@owners );
+  my ($res, $errmsg) = $session->load_shared(Vici::Message->new(\%vars));
+
+=cut
+
+print "----- load-shared -----\n";
+my @owners = ( 'carol' );
+%vars = ( type => 'EAP', data => 'Ar3etTnp', owners => \@owners );
+($res, $errmsg) = $session->load_shared(Vici::Message->new(\%vars));
+print $res ? "ok\n" : "failed: $errmsg\n";
+
+=item load_authority()
+
+loads a single certification authority definition into the daemon. An existing
+authority with the same name gets replaced.
+
+  my @crl_uris  = ( 'http://crl.strongswan.org/strongswan.crl' );
+  my @ocsp_uris = ( 'http://ocsp.strongswan.org:8880' );
+
+  my %auth = (
+      cacert => $ca_cert,
+      crl_uris  => \@crl_uris,
+      ocsp_uris => \@ocsp_uris
+  );
+
+  my %vars = ( strongswan => \%auth );
+  my ($res, $errmsg) = $session->load_authority(Vici::Message->new(\%vars));
+
+=cut
+
+print "----- load-authority -----\n";
+my @crl_uris  = ( 'http://crl.strongswan.org/strongswan.crl' );
+my @ocsp_uris = ( 'http://ocsp.strongswan.org:8880' );
+my %auth = (
+    cacert => $ca_cert,
+    crl_uris  => \@crl_uris,
+    ocsp_uris => \@ocsp_uris
+);
+%vars = ( strongswan => \%auth );
+($res, $errmsg) = $session->load_authority(Vici::Message->new(\%vars));
+print $res ? "ok\n" : "failed: $errmsg\n";
+
+=item load_conn()
+
+loads a single connection definition into the daemon. An existing connection
+with the same name gets updated or replaced.
+
+  my @l_ts = ( '10.1.0.0/16' );
+  my @r_ts = ( '10.2.0.0/16' );
+  my @esp  = ( 'aes128gcm128-modp3072' );
+
+  my %child = (
+      local_ts  => \@l_ts,
+      remote_ts => \@r_ts,
+      esp_proposals => \@esp,
+  );
+  my %children = ( 'net-net' => \%child );
+
+  my @l_addrs = ( '192.168.0.1' );
+  my @r_addrs = ( '192.168.0.2' );
+  my @l_certs = ( $moon_cert );
+  my %l = ( auth => 'pubkey', id => 'moon.strongswan.org',
+            certs => \@l_certs );
+  my %r = ( auth => 'pubkey', id => 'sun.strongswan.org');
+  my @ike = ( 'aes128-sha256-modp3072' );
+
+  my %gw = (
+      version => 2,
+      mobike => 'no',
+      proposals => \@ike,
+      local_addrs  => \@l_addrs,
+      remote_addrs => \@r_addrs,
+      local  => \%l,
+      remote => \%r,
+      children => \%children,
+  );
+
+  my %vars = ( 'gw-gw' => \%gw);
+  my ($res, $errmsg) = $session->load_conn(Vici::Message->new(\%vars));
+
+=cut
+
+print "----- load-conn -----\n";
+my @l_ts = ( '10.1.0.0/16' );
+my @r_ts = ( '10.2.0.0/16' );
+my @esp  = ( 'aes128gcm128-modp3072' );
+my %child = (
+    local_ts  => \@l_ts,
+    remote_ts => \@r_ts,
+    esp_proposals => \@esp,
+);  
+my %children = ( 'net-net' => \%child );
+my @l_addrs = ( '192.168.0.1' );
+my @r_addrs = ( '192.168.0.2' );
+my @l_certs = ( $moon_cert );
+my %l = ( auth => 'pubkey', id => 'moon.strongswan.org', certs => \@l_certs );
+my %r = ( auth => 'pubkey', id => 'sun.strongswan.org');
+my @ike = ( 'aes128-sha256-modp3072' );
+my %gw = (
+    version => 2,
+    mobike => 'no',
+    proposals => \@ike,
+    local_addrs  => \@l_addrs,
+    remote_addrs => \@r_addrs,
+    local  => \%l,
+    remote => \%r,
+    children => \%children,
+);
+%vars = ( 'gw-gw' => \%gw);
+($res, $errmsg) = $session->load_conn(Vici::Message->new(\%vars));
+print $res ? "ok\n" : "failed: $errmsg\n";
+
+=item get_algorithms()
+
+lists all currently loaded algorithms and their implementation.
+
+  my $algs = $session->get_algorithms();
+
+=cut
+
+print "----- get-algorithms -----\n";
+my $algs = $session->get_algorithms();
+print $algs->raw(), "\n";
+
+=item get_conns()
+
+returns a list of connection names loaded exclusively over VICI, not including
+connections found in other backends.
+
+  my $conns = $session->get_conns();
+
+=cut
+
+print "----- get-conns -----\n";
+my $conns = $session->get_conns();
+print $conns->raw(), "\n";
+
+=item list_conns()
+
+lists currently loaded connections by streaming list-conn events. This
+call includes all connections known by the daemon, not only those loaded
+over VICI.
+
+  my $conns = $session->list_conns();
+
+  foreach my $conn (@$conns)
+  {
+      print $conn->raw(), "\n";
+  }
+
+=cut
+
+print "----- list-conns -----\n";
+$conns = $session->list_conns();
+foreach my $conn (@$conns)
+{
+    print $conn->raw(), "\n";
+}
+
+=item initiate()
+
+initiates a CHILD_SA.
+
+  my %vars = ( child => 'net-net' );
+  my($res, $errmsg) = $session->initiate(Vici::Message->new(\%vars));
+
+=cut
+
+print "----- initiate -----\n";
+%vars = ( child => 'net-net' );
+($res, $errmsg) = $session->initiate(Vici::Message->new(\%vars));
+print $res ? "ok\n" : "failed: $errmsg\n";
+
+=item list_sas()
+
+lists currently active IKE_SAs and associated CHILD_SAs by streaming list-sa
+events.
+
+  my $sas = $session->list_sas();
+
+  foreach my $sa (@$sas)
+  {
+      print $sa->raw(), "\n";
+  }
+
+=cut
+
+print "----- list-sas -----\n";
+my $sas = $session->list_sas();
+foreach my $sa (@$sas)
+{
+    print $sa->raw(), "\n";
+}
+
+=item get_authorities()
+
+returns a list of currently loaded certification authority names.
+
+  my $auths = $session->get_authorities();
+
+=cut
+
+print "----- get-authorities -----\n";
+my $auths = $session->get_authorities();
+print $auths->raw(), "\n";
+
+=item list-authorities()
+
+lists currently loaded certification authority information by streaming
+list-authority events.
+
+  my $auths = $session->list_authorities();
+
+  foreach my $auth (@$auths)
+  {
+      print $auth->raw(), "\n";
+  }
+
+=cut
+
+print "----- list-authorities -----\n";
+$auths = $session->list_authorities();
+foreach my $auth (@$auths)
+{
+    print $auth->raw(), "\n";
+}
+
+=item list_certs()
+
+lists currently loaded certificates by streaming list-cert events. This
+call includes all certificates known by the daemon, not only those loaded
+over VICI.
+
+  my %vars = ( subject => 'C=CH, O=Linux strongSwan, CN=moon.strongswan.org' );
+  my $certs = $session->list_certs(Vici::Message->new(\%vars));
+
+=cut
+
+print "----- list-certs -----\n";
+%vars = ( subject => 'C=CH, O=Linux strongSwan, CN=moon.strongswan.org' );
+my $certs = $session->list_certs(Vici::Message->new(\%vars));
+foreach my $cert (@$certs)
+{
+    my $hash = $cert->hash();
+    print $hash->{'type'}, ": ", length($hash->{'data'}), ' bytes',
+          $hash->{'has_privkey'} ? ', has private key' : '', "\n";
+}
+
+=item stats()
+
+returns IKE daemon statistics and load information.
+
+  my $stats = $session->stats();
+
+=cut
+
+print "----- stats -----\n";
+my $stats = $session->stats();
+print $stats->raw(), "\n";
+
+=item terminate()
+
+terminates an IKE_SA or CHILD_SA.
+
+  my %vars = ( ike => 'gw-gw' );
+  my ($res, $errmsg) = $session->terminate(Vici::Message->new(\%vars));
+
+=cut
+
+print "----- terminate -----\n";
+%vars = ( ike => 'gw-gw' );
+($res, $errmsg) = $session->terminate(Vici::Message->new(\%vars));
+print $res ? "ok\n" : "failed: $errmsg\n";
+
+=item install()
+
+installs a trap, drop or bypass policy defined by a CHILD_SA config.
+
+  my %vars = ( child => 'net-net' );
+  my ($res, $errmsg) = $session->install(Vici::Message->new(\%vars));
+
+=cut
+
+print "----- install -----\n";
+%vars = ( child => 'net-net' );
+($res, $errmsg) = $session->install(Vici::Message->new(\%vars));
+print $res ? "ok\n" : "failed: $errmsg\n";
+
+=item list_policies()
+
+lists currently installed trap, drop and bypass policies by streaming
+list-policy events.
+
+  my %vars = ( trap => 'yes' );
+  my $pols = $session->list_policies(Vici::Message->new(\%vars));
+
+  foreach my $pol (@$pols)
+  {
+      print $pol->raw(), "\n";
+  }
+
+=cut
+
+print "----- list-policies -----\n";
+%vars = ( trap => 'yes' );
+my $pols = $session->list_policies(Vici::Message->new(\%vars));
+foreach my $pol (@$pols)
+{
+    print $pol->raw(), "\n";
+}
+
+=item uninstall()
+
+uninstalls a trap, drop or bypass policy defined by a CHILD_SA config.
+
+  my %vars = ( child => 'net-net' );
+  my ($res, $errmsg) = $session->uninstall(Vici::Message->new(\%vars));
+
+=cut
+
+print "----- uninstall -----\n";
+%vars = ( child => 'net-net' );
+($res, $errmsg) = $session->uninstall(Vici::Message->new(\%vars));
+print $res ? "ok\n" : "failed: $errmsg\n";
+
+=item reload_settings()
+
+reloads strongswan.conf settings and all plugins supporting configuration
+reload.
+
+  my ($res, $errmsg) = $session->reload_settings();
+  print $res ? "ok\n" : "failed: $errmsg\n";
+
+=cut
+
+print "----- reload-settings -----\n";
+($res, $errmsg) = $session->reload_settings();
+print $res ? "ok\n" : "failed: $errmsg\n";
+
+=item unload_conn()
+
+unloads a previously loaded connection definition by name.
+
+  my %vars = ( name => 'gw-gw' );
+  my ($res, $errmsg) = $session->unload_conn(Vici::Message->new(\%vars));
+
+=cut
+
+print "----- unload-conn -----\n";
+%vars = ( name => 'gw-gw' );
+($res, $errmsg) = $session->unload_conn(Vici::Message->new(\%vars));
+print $res ? "ok\n" : "failed: $errmsg\n";
+
+=item unload_authority()
+
+unloads a previously loaded certification authority definition by name.
+
+  my %vars = ( name => 'strongswan' );
+  my ($res, $errmsg) = $session->unload_authority(Vici::Message->new(\%vars));
+
+=cut
+
+print "----- unload-authority -----\n";
+%vars = ( name => 'strongswan' );
+($res, $errmsg) = $session->unload_authority(Vici::Message->new(\%vars));
+print $res ? "ok\n" : "failed: $errmsg\n";
+
+=item clear_creds()
+
+clears all loaded certificate, private key and shared key credentials. This
+affects only credentials loaded over vici, but additionally flushes the
+credential cache.
+
+  my ($res, $errmsg) = $session->clear_creds();
+
+=cut
+
+print "----- clear-creds -----\n";
+($res, $errmsg) = $session->clear_creds();
+print $res ? "ok\n" : "failed: $errmsg\n";
+
+=item load_pool()
+
+loads an in-memory virtual IP and configuration attribute pool. Existing
+pools with the same name get updated, if possible.
+
+  my %pool = ( addrs => '10.3.0.0/23' );
+  my %vars = ( my_pool => \%pool );
+  my ($res, $errmsg) = $session->load_pool(Vici::Message->new(\%vars));
+
+=cut
+
+print "----- load-pool -----\n";
+my %pool = ( addrs => '10.3.0.0/23' );
+%vars = ( my_pool => \%pool );
+($res, $errmsg) = $session->load_pool(Vici::Message->new(\%vars));
+print $res ? "ok\n" : "failed: $errmsg\n";
+
+=item get_pools()
+
+lists the currently loaded pools.
+
+  my $pools = $session->get_pools();
+
+=cut
+
+print "----- get-pools -----\n";
+my $pools = $session->get_pools();
+print $pools->raw(), "\n";
+
+=item unload_pool()
+
+unloads a previously loaded virtual IP and configuration attribute pool.
+Unloading fails for pools with leases currently online.
+
+  my %vars = ( name => 'my_pool' );
+  my ($res, $errmsg) = $session->unload_pool(Vici::Message->new(\%vars));
+
+=cut
+
+print "----- unload-pool -----\n";
+%vars = ( name => 'my_pool' );
+($res, $errmsg) = $session->unload_pool(Vici::Message->new(\%vars));
+print $res ? "ok\n" : "failed: $errmsg\n";
+
+=back
+
+=cut
+
+# close vici socket
+close($socket);
+
+=head1 COPYRIGHT AND LICENCE
+
+Copyright (c) 2015 Andreas Steffen
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Message.pm b/src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Message.pm
new file mode 100644
index 0000000..b0a942c
--- /dev/null
+++ b/src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Message.pm
@@ -0,0 +1,256 @@
+package Vici::Message;
+
+our $VERSION = '0.9';
+
+use strict;
+use Vici::Transport;
+
+use constant {
+    SECTION_START => 1,   # Begin a new section having a name
+    SECTION_END   => 2,   # End a previously started section
+    KEY_VALUE     => 3,   # Define a value for a named key in the section
+    LIST_START    => 4,   # Begin a named list for list items
+    LIST_ITEM     => 5,   # Define an unnamed item value in the current list
+    LIST_END      => 6,   # End a previously started list
+};
+
+sub new {
+    my $class = shift;
+    my $hash = shift;
+    my $self = {
+        Hash => $hash
+    };
+    bless($self, $class);
+    return $self;
+}
+
+sub from_data {
+    my $class = shift;
+    my $data = shift;
+    my %hash = ();
+
+    parse($data, \%hash);
+
+    my $self = {
+        Hash => \%hash
+    };
+    bless($self, $class);
+    return $self;
+}
+
+sub hash {
+    my $self = shift;
+    return $self->{Hash};
+}
+
+sub encode {
+    my $self = shift;
+    return encode_hash($self->{'Hash'});
+}
+
+sub raw {
+    my $self = shift;
+    return '{' . raw_hash($self->{'Hash'}) . '}';
+}
+
+sub result {
+    my $self = shift;
+    my $result = $self->{'Hash'};
+    return ($result->{'success'} eq 'yes', $result->{'errmsg'});
+}
+
+# private functions
+
+sub parse {
+    my $data = shift;
+    my $hash = shift;
+
+    while (length($data) > 0)
+    {
+        (my $type, $data) = unpack('Ca*', $data);
+
+		if ($type == SECTION_END)
+		{
+			return $data;
+		}
+
+        (my $key, $data) = unpack('C/a*a*', $data);
+
+        if ( $type == KEY_VALUE )
+        {
+            (my $value, $data) = unpack('n/a*a*', $data);
+            $hash->{$key} = $value;
+        }
+        elsif ( $type == SECTION_START )
+        {
+            my %section = ();
+            $data = parse($data, \%section);
+            $hash->{$key} = \%section;
+        }
+        elsif ( $type == LIST_START )
+        {
+            my @list = ();
+            my $more = 1;
+
+            while (length($data) > 0 and $more)
+            {
+                (my $type, $data) = unpack('Ca*', $data);
+                if ( $type == LIST_ITEM )
+                {
+                    (my $value, $data) = unpack('n/a*a*', $data);
+                    push(@list, $value);
+                }
+                elsif ( $type == LIST_END )
+                {
+                    $more = 0;
+                    $hash->{$key} = \@list;
+                 }
+                else
+                {
+                    die "message parsing error: ", $type, "\n"
+                }
+            }
+        }
+        else
+        {
+            die "message parsing error: ", $type, "\n"
+        }
+    }
+    return $data;
+}
+
+
+sub encode_hash {
+    my $hash = shift;
+    my $enc = '';
+
+    while ( (my $key, my $value) = each %$hash )
+    {
+        if ( ref($value) eq 'HASH' )
+        {
+            $enc .= pack('CC/a*', SECTION_START, $key);
+            $enc .= encode_hash($value);
+            $enc .= pack('C', SECTION_END);
+        }
+        elsif ( ref($value) eq 'ARRAY' )
+        {
+            $enc .= pack('CC/a*', LIST_START, $key);
+
+            foreach my $item (@$value)
+            {
+                $enc .= pack('Cn/a*', LIST_ITEM, $item);
+            }
+            $enc .= pack('C', LIST_END);
+        }
+        else
+        {
+            $enc .= pack('CC/a*n/a*', KEY_VALUE, $key, $value);
+        }
+    }
+    return $enc;
+}
+
+sub raw_hash {
+    my $hash = shift;
+    my $raw = '';
+    my $first = 1;
+
+    while ( (my $key, my $value) = each %$hash )
+    {
+        if ($first)
+        {
+            $first = 0;
+        }
+        else
+        {
+            $raw .= ' ';
+        }
+        $raw .= $key;
+
+        if ( ref($value) eq 'HASH' )
+        {
+            $raw .= '{' . raw_hash($value) . '}';
+        }
+        elsif ( ref($value) eq 'ARRAY' )
+        {
+            my $first_item = 1;
+            $raw .= '[';
+
+            foreach my $item (@$value)
+            {
+                if ($first_item)
+                {
+                    $first_item = 0;
+                }
+                else
+                {
+                    $raw .= ' ';
+                }
+                $raw .= $item;
+            }
+            $raw .= ']';
+        }
+        else
+        {
+            $raw .= '=' . $value;
+        }
+    }
+    return $raw;
+}
+
+1;
+__END__
+=head1 NAME
+
+Vici::Message - Perl extension for building and parsing strongSwan VICI messages
+
+=head1 SYNOPSIS
+
+  use Vici::Message;
+
+=head1 DESCRIPTION
+
+The Vici::Message module is needed by the Vici::Session module to build and
+parse messages used in the communication with the open source strongSwan IPsec
+daemon (https://www.strongswan.com) via the documented Versatile IKE
+Configuration Interface (VICI). VICI allows the configuration, management and
+monitoring of multiple IPsec connections.
+
+=head2 EXPORT
+
+None by default.
+
+=head1 SEE ALSO
+
+strongSwan Wiki:  https://wiki.strongswan.org/projects/strongswan/wiki/Vici
+
+strongSwan Mailing list:  users at lists.strongswan.org
+
+=head1 AUTHOR
+
+Andreas Steffen, E<lt>andreas.steffen at strongswan.orgE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2015 by Andreas Steffen
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+=cut
+
diff --git a/src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Packet.pm b/src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Packet.pm
new file mode 100644
index 0000000..9e2b77f
--- /dev/null
+++ b/src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Packet.pm
@@ -0,0 +1,191 @@
+package Vici::Packet;
+
+our $VERSION = '0.9';
+
+use strict;
+use Vici::Message;
+use Vici::Transport;
+
+use constant {
+    CMD_REQUEST      => 0,  # Named request message
+    CMD_RESPONSE     => 1,  # Unnamed response message for a request
+    CMD_UNKNOWN      => 2,  # Unnamed response if requested command is unknown
+    EVENT_REGISTER   => 3,  # Named event registration request
+    EVENT_UNREGISTER => 4,  # Named event de-registration request
+    EVENT_CONFIRM    => 5,  # Unnamed confirmation for event (de-)registration
+    EVENT_UNKNOWN    => 6,  # Unnamed response if event (de-)registration failed
+    EVENT            => 7,  # Named event message
+};
+
+sub new {
+    my $class = shift;
+    my $socket = shift;
+    my $self = {
+       Transport => Vici::Transport->new($socket),
+    };
+    bless($self, $class);
+    return $self;
+}
+
+sub request {
+    my ($self, $command, $vars) = @_;
+    my $out = defined $vars ? $vars->encode() : '';
+    my $request = pack('CC/a*a*', CMD_REQUEST, $command, $out);
+    $self->{'Transport'}->send($request);
+
+    my $response = $self->{'Transport'}->receive();
+    my ($type, $data) = unpack('Ca*', $response);
+
+    if ( $type == CMD_RESPONSE )
+    {
+        return Vici::Message->from_data($data);
+    }
+    elsif ( $type == CMD_UNKNOWN )
+    {
+        die "unknown command '", $command, "'\n"
+    }
+    else
+    {
+        die "invalid response type\n"
+    }
+}
+
+sub register {
+    my ($self, $event) = @_;
+    my $request = pack('CC/a*a*', EVENT_REGISTER, $event);
+    $self->{'Transport'}->send($request);
+
+    my $response = $self->{'Transport'}->receive();
+    my ($type, $data) = unpack('Ca*', $response);
+
+    if ( $type == EVENT_CONFIRM )
+    {
+        return
+    }
+    elsif ( $type == EVENT_UNKNOWN )
+    {
+        die "unknown event '", $event, "'\n"
+    }
+    else
+    {
+        die "invalid response type\n"
+    }
+}
+
+sub unregister {
+    my ($self, $event) = @_;
+    my $request = pack('CC/a*a*', EVENT_UNREGISTER, $event);
+    $self->{'Transport'}->send($request);
+
+    my $response = $self->{'Transport'}->receive();
+    my ($type, $data) = unpack('Ca*', $response);
+
+    if ( $type == EVENT_CONFIRM )
+    {
+        return
+    }
+    elsif ( $type == EVENT_UNKNOWN )
+    {
+        die "unknown event '", $event, "'\n"
+    }
+    else
+    {
+        die "invalid response type\n"
+    }
+}
+
+sub streamed_request {
+    my ($self, $command, $event, $vars) = @_;
+    my $out = defined $vars ? $vars->encode() : '';
+
+   $self->register($event);
+
+    my $request = pack('CC/a*a*', CMD_REQUEST, $command, $out);
+    $self->{'Transport'}->send($request);
+    my $more = 1;
+    my @list = ();
+
+    while ($more)
+    {
+        my $response = $self->{'Transport'}->receive();
+        my ($type, $data) = unpack('Ca*', $response);
+
+        if ( $type == EVENT )
+        {
+           (my $event_name, $data) = unpack('C/a*a*', $data);
+
+           if ($event_name eq $event)
+           {
+               my $msg = Vici::Message->from_data($data);
+               push(@list, $msg);
+           }
+        }
+        elsif ( $type == CMD_RESPONSE )
+        {
+            $self->unregister($event);
+            $more = 0;
+        }
+        else
+        {
+            $self->unregister($event);
+            die "invalid response type\n";
+        }
+    }
+    return \@list;
+}
+
+1;
+__END__
+=head1 NAME
+
+Vici::Packet - Perl extension for sending and receiving strongSwan VICI packets
+
+=head1 SYNOPSIS
+
+  use Vici::Packet;
+
+=head1 DESCRIPTION
+
+The Vici::Packet module is needed by the Vici::Session module to send and
+receive packets used in the communication with the open source strongSwan IPsec
+daemon (https://www.strongswan.com) via the documented Versatile IKE
+Configuration Interface (VICI). VICI allows the configuration, management and
+monitoring of multiple IPsec connections.
+
+=head2 EXPORT
+
+None by default.
+
+=head1 SEE ALSO
+
+strongSwan Wiki:  https://wiki.strongswan.org/projects/strongswan/wiki/Vici
+
+strongSwan Mailing list:  users at lists.strongswan.org
+
+=head1 AUTHOR
+
+Andreas Steffen, E<lt>andreas.steffen at strongswan.orgE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2015 by Andreas Steffen
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+=cut
diff --git a/src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Session.pm b/src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Session.pm
new file mode 100644
index 0000000..7819713
--- /dev/null
+++ b/src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Session.pm
@@ -0,0 +1,204 @@
+package Vici::Session;
+
+our $VERSION = '0.9';
+
+use strict;
+use Vici::Packet;
+use Vici::Message;
+
+sub new {
+    my $class = shift;
+    my $socket = shift;
+    my $self = {
+        Packet => Vici::Packet->new($socket),
+    };
+    bless($self, $class);
+    return $self;
+}
+
+sub version {
+    return request('version', @_);
+}
+
+sub stats {
+    return request('stats', @_);
+}
+
+sub reload_settings {
+   return request_res('reload-settings', @_);
+}
+
+sub initiate {
+    return request_vars_res('initiate', @_);
+}
+
+sub terminate {
+    return request_vars_res('terminate', @_);
+}
+
+sub redirect {
+    return request_vars_res('redirect', @_);
+}
+
+sub install {
+    return request_vars_res('install', @_);
+}
+
+sub uninstall {
+    return request_vars_res('uninstall', @_);
+}
+
+sub list_sas {
+    return request_list('list-sas', 'list-sa', @_);
+}
+
+sub list_policies {
+    return request_list('list-policies', 'list-policy', @_);
+}
+
+sub list_conns {
+    return request_list('list-conns', 'list-conn', @_);
+}
+
+sub get_conns {
+    return request('get-conns', @_);
+}
+
+sub list_certs {
+    return request_list('list-certs', 'list-cert', @_);
+}
+
+sub list_authorities {
+    return request_list('list-authorities', 'list-authority', @_);
+}
+
+sub get_authorities {
+    return request('get-authorities', @_);
+}
+
+sub load_conn {
+    return request_vars_res('load-conn', @_);
+}
+
+sub unload_conn {
+    return request_vars_res('unload-conn', @_);
+}
+
+sub load_cert {
+    return request_vars_res('load-cert', @_);
+}
+
+sub load_key {
+    return request_vars_res('load-key', @_);
+}
+
+sub load_shared {
+    return request_vars_res('load-shared', @_);
+}
+
+sub clear_creds {
+   return request_res('clear-creds', @_);
+}
+
+sub load_authority {
+    return request_vars_res('load-authority', @_);
+}
+
+sub unload_authority {
+    return request_vars_res('unload-authority', @_);
+}
+
+sub load_pool {
+    return request_vars_res('load-pool', @_);
+}
+
+sub unload_pool {
+    return request_vars_res('unload-pool', @_);
+}
+
+sub get_pools {
+    return request('get-pools', @_);
+}
+
+sub get_algorithms {
+    return request('get-algorithms', @_);
+}
+
+# Private functions
+
+sub request {
+    my ($command, $self) = @_;
+    return $self->{'Packet'}->request($command);
+}
+
+sub request_res {
+    my ($command, $self) = @_;
+    my $msg = $self->{'Packet'}->request($command);
+    return $msg->result();
+}
+
+sub request_vars_res {
+    my ($command, $self, $vars) = @_;
+    my $msg = $self->{'Packet'}->request($command, $vars);
+    return $msg->result();
+}
+
+sub request_list {
+    my ($command, $event, $self, $vars) = @_;
+    return $self->{'Packet'}->streamed_request($command, $event, $vars);
+}
+
+1;
+__END__
+=head1 NAME
+
+Vici::Session - Perl binding for the strongSwan VICI configuration interface
+
+=head1 SYNOPSIS
+
+  use Vici::Session;
+
+=head1 DESCRIPTION
+
+The Vici::Session module allows a Perl script to communicate with the open
+source strongSwan IPsec daemon (https://www.strongswan.com) via the documented
+Versatile IKE Configuration Interface (VICI). VICI allows the configuration,
+management and monitoring of multiple IPsec connections.
+
+=head2 EXPORT
+
+None by default.
+
+=head1 SEE ALSO
+
+strongSwan Wiki:  https://wiki.strongswan.org/projects/strongswan/wiki/Vici
+
+strongSwan Mailing list:  users at lists.strongswan.org
+
+=head1 AUTHOR
+
+Andreas Steffen, E<lt>andreas.steffen at strongswan.orgE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2015 by Andreas Steffen
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+=cut
diff --git a/src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Transport.pm b/src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Transport.pm
new file mode 100644
index 0000000..6524bf7
--- /dev/null
+++ b/src/libcharon/plugins/vici/perl/Vici-Session/lib/Vici/Transport.pm
@@ -0,0 +1,88 @@
+package Vici::Transport;
+
+our $VERSION = '0.9';
+
+use strict;
+
+sub new {
+    my $class = shift;
+    my $self = {
+        Socket => shift,
+    };
+    bless($self, $class);
+    return $self;
+}
+
+sub send {
+    my ($self, $data) = @_;
+    my $packet = pack('N/a*', $data);
+    $self->{'Socket'}->send($packet);
+}
+
+sub receive {
+    my $self = shift;
+    my $packet_header;
+    my $data;
+
+    $self->{'Socket'}->recv($packet_header, 4);
+    my $packet_len = unpack('N', $packet_header);
+    $self->{'Socket'}->recv($data, $packet_len);
+	return $data;
+}
+
+1;
+__END__
+=head1 NAME
+
+Vici::Transport - Perl extension for communicating via a strongSwan VICI socket
+
+=head1 SYNOPSIS
+
+  use Vici::Transport;
+
+=head1 DESCRIPTION
+
+The Vici::Transport module is needed by the Vici::Packet module to send
+and receive packets over the UNIX socket used in the communication with the
+open source strongSwan IPsec daemon (https://www.strongswan.com) via the
+documented Versatile IKE Configuration Interface (VICI). VICI allows the
+onfiguration, management and monitoring of multiple IPsec connections.
+
+=head2 EXPORT
+
+None by default.
+
+=head1 SEE ALSO
+
+strongSwan Wiki:  https://wiki.strongswan.org/projects/strongswan/wiki/Vici
+
+strongSwan Mailing list:  users at lists.strongswan.org
+
+=head1 AUTHOR
+
+Andreas Steffen, E<lt>andreas.steffen at strongswan.orgE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2015 by Andreas Steffen
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+=cut
+
diff --git a/src/libcharon/plugins/vici/perl/Vici-Session/t/Vici-Session.t b/src/libcharon/plugins/vici/perl/Vici-Session/t/Vici-Session.t
new file mode 100644
index 0000000..4c321f3
--- /dev/null
+++ b/src/libcharon/plugins/vici/perl/Vici-Session/t/Vici-Session.t
@@ -0,0 +1,18 @@
+# Before 'make install' is performed this script should be runnable with
+# 'make test'. After 'make install' it should work as 'perl Vici-Session.t'
+
+#########################
+
+# change 'tests => 1' to 'tests => last_test_to_print';
+
+use strict;
+use warnings;
+
+use Test::More tests => 1;
+BEGIN { use_ok('Vici::Session') };
+
+#########################
+
+# Insert your test code below, the Test::More module is use()ed here so read
+# its man page ( perldoc Test::More ) for help writing this test script.
+
diff --git a/src/libcharon/plugins/vici/python/Makefile.in b/src/libcharon/plugins/vici/python/Makefile.in
index eb4bab6..894a7e2 100644
--- a/src/libcharon/plugins/vici/python/Makefile.in
+++ b/src/libcharon/plugins/vici/python/Makefile.in
@@ -351,6 +351,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libcharon/plugins/vici/python/vici/session.py b/src/libcharon/plugins/vici/python/vici/session.py
index 283e3d1..66de859 100644
--- a/src/libcharon/plugins/vici/python/vici/session.py
+++ b/src/libcharon/plugins/vici/python/vici/session.py
@@ -53,6 +53,14 @@ class Session(object):
         """
         return self.handler.streamed_request("terminate", "control-log", sa)
 
+    def redirect(self, sa):
+        """Redirect an IKE_SA.
+
+        :param sa: the SA to redirect
+        :type sa: dict
+        """
+        self.handler.request("redirect", sa)
+
     def install(self, policy):
         """Install a trap, drop or bypass policy defined by a CHILD_SA config.
 
diff --git a/src/libcharon/plugins/vici/ruby/Makefile.in b/src/libcharon/plugins/vici/ruby/Makefile.in
index bf81e53..b87d83d 100644
--- a/src/libcharon/plugins/vici/ruby/Makefile.in
+++ b/src/libcharon/plugins/vici/ruby/Makefile.in
@@ -329,6 +329,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libcharon/plugins/vici/ruby/lib/vici.rb b/src/libcharon/plugins/vici/ruby/lib/vici.rb
index f8169ad..018f507 100644
--- a/src/libcharon/plugins/vici/ruby/lib/vici.rb
+++ b/src/libcharon/plugins/vici/ruby/lib/vici.rb
@@ -505,6 +505,12 @@ module Vici
     end
 
     ##
+    # Redirect an IKE_SA.
+    def redirect(options)
+      check_success(@transp.request("redirect", Message.new(options)))
+    end
+
+    ##
     # Install a shunt/route policy.
     def install(policy)
       check_success(@transp.request("install", Message.new(policy)))
diff --git a/src/libcharon/plugins/vici/vici_cert_info.c b/src/libcharon/plugins/vici/vici_cert_info.c
new file mode 100644
index 0000000..2f278de
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_cert_info.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR 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.
+ */
+
+#include "vici_cert_info.h"
+
+/**
+ * Legacy vici certificate types and directories created by swanctl
+ */
+typedef struct {
+
+	/** Certificate type string used in legacy vici messages */
+	char *type_str;
+	/** Base certificate type */
+	certificate_type_t type;
+	/** X.509 flag */
+	x509_flag_t flag;
+} cert_type_t;
+
+static cert_type_t cert_types[] = {
+	{ "x509",     CERT_X509,           X509_NONE        },
+	{ "x509ca",   CERT_X509,           X509_CA          },
+	{ "x509ocsp", CERT_X509,           X509_OCSP_SIGNER },
+	{ "x509aa",   CERT_X509,           X509_AA          },
+	{ "x509ac",   CERT_X509_AC,        X509_NONE        },
+	{ "x509crl",  CERT_X509_CRL,       X509_NONE        },
+	{ "pubkey",   CERT_TRUSTED_PUBKEY, X509_NONE        },
+};
+
+bool vici_cert_info_from_str(char *type_str, certificate_type_t *type,
+							 x509_flag_t *flag)
+{
+	int i;
+
+	for (i = 0; i < countof(cert_types); i++)
+	{
+		if (strcaseeq(type_str, cert_types[i].type_str))
+		{
+			*type = cert_types[i].type;
+			*flag = cert_types[i].flag;
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
diff --git a/src/libcharon/plugins/vici/vici_cert_info.h b/src/libcharon/plugins/vici/vici_cert_info.h
new file mode 100644
index 0000000..e2a8c4d
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_cert_info.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR 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 vici_cert_info vici_cert_info
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_CERT_INFO_H_
+#define VICI_CERT_INFO_H_
+
+typedef struct vici_cert_info_t vici_cert_info_t;
+
+#include <credentials/certificates/certificate.h>
+#include <credentials/certificates/x509.h>
+
+bool vici_cert_info_from_str(char *type_str, certificate_type_t *type,
+							 x509_flag_t *flag);
+
+#endif /** VICI_CERT_INFO_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c
index ea6d295..6ebbedc 100644
--- a/src/libcharon/plugins/vici/vici_config.c
+++ b/src/libcharon/plugins/vici/vici_config.c
@@ -2,7 +2,8 @@
  * Copyright (C) 2014 Martin Willi
  * Copyright (C) 2014 revosec AG
  *
- * Copyright (C) 2015 Andreas Steffen
+ * Copyright (C) 2015-2016 Tobias Brunner
+ * Copyright (C) 2015-2016 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -45,9 +46,12 @@
 
 #include <daemon.h>
 #include <threading/rwlock.h>
+#include <threading/rwlock_condvar.h>
 #include <collections/array.h>
 #include <collections/linked_list.h>
 
+#include <pubkey_cert.h>
+
 #include <stdio.h>
 
 /**
@@ -98,6 +102,21 @@ struct private_vici_config_t {
 	rwlock_t *lock;
 
 	/**
+	 * Condvar used to snyc running actions
+	 */
+	rwlock_condvar_t *condvar;
+
+	/**
+	 * True while we run or undo a start action
+	 */
+	bool handling_actions;
+
+	/**
+	 * Credential backend managed by VICI used for our certificates
+	 */
+	vici_cred_t *cred;
+
+	/**
 	 * Auxiliary certification authority information
 	 */
 	vici_authority_t *authority;
@@ -218,6 +237,24 @@ typedef struct {
 } request_data_t;
 
 /**
+ * Auth config data
+ */
+typedef struct {
+	request_data_t *request;
+	auth_cfg_t *cfg;
+	u_int32_t round;
+} auth_data_t;
+
+/**
+ * Clean up auth config data
+ */
+static void free_auth_data(auth_data_t *data)
+{
+	DESTROY_IF(data->cfg);
+	free(data);
+}
+
+/**
  * Data associated to a peer config
  */
 typedef struct {
@@ -311,7 +348,7 @@ static void log_auth(auth_cfg_t *auth)
 static void log_peer_data(peer_data_t *data)
 {
 	enumerator_t *enumerator;
-	auth_cfg_t *auth;
+	auth_data_t *auth;
 	host_t *host;
 
 	DBG2(DBG_CFG, "  version = %u", data->version);
@@ -350,7 +387,7 @@ static void log_peer_data(peer_data_t *data)
 	while (enumerator->enumerate(enumerator, &auth))
 	{
 		DBG2(DBG_CFG, "  local:");
-		log_auth(auth);
+		log_auth(auth->cfg);
 	}
 	enumerator->destroy(enumerator);
 
@@ -358,7 +395,7 @@ static void log_peer_data(peer_data_t *data)
 	while (enumerator->enumerate(enumerator, &auth))
 	{
 		DBG2(DBG_CFG, "  remote:");
-		log_auth(auth);
+		log_auth(auth->cfg);
 	}
 	enumerator->destroy(enumerator);
 }
@@ -368,10 +405,8 @@ static void log_peer_data(peer_data_t *data)
  */
 static void free_peer_data(peer_data_t *data)
 {
-	data->local->destroy_offset(data->local,
-									offsetof(auth_cfg_t, destroy));
-	data->remote->destroy_offset(data->remote,
-									offsetof(auth_cfg_t, destroy));
+	data->local->destroy_function(data->local, (void*)free_auth_data);
+	data->remote->destroy_function(data->remote, (void*)free_auth_data);
 	data->children->destroy_offset(data->children,
 									offsetof(child_cfg_t, destroy));
 	data->proposals->destroy_offset(data->proposals,
@@ -461,14 +496,6 @@ static void free_child_data(child_data_t *data)
 }
 
 /**
- * Auth config data
- */
-typedef struct {
-	request_data_t *request;
-	auth_cfg_t *cfg;
-} auth_data_t;
-
-/**
  * Common proposal parsing
  */
 static bool parse_proposal(linked_list_t *list, protocol_id_t proto, chunk_t v)
@@ -537,7 +564,7 @@ CALLBACK(parse_ts, bool,
 	linked_list_t *out, chunk_t v)
 {
 	char buf[128], *protoport, *sep, *port = "", *end;
-	traffic_selector_t *ts;
+	traffic_selector_t *ts = NULL;
 	struct protoent *protoent;
 	struct servent *svc;
 	long int p;
@@ -630,6 +657,22 @@ CALLBACK(parse_ts, bool,
 	{
 		ts = traffic_selector_create_dynamic(proto, from, to);
 	}
+	else if (strchr(buf, '-'))
+	{
+		host_t *lower, *upper;
+		ts_type_t type;
+
+		if (host_create_from_range(buf, &lower, &upper))
+		{
+			type = (lower->get_family(lower) == AF_INET) ?
+						 		TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE;
+			ts = traffic_selector_create_from_bytes(proto, type,
+								lower->get_address(lower), from,
+								upper->get_address(upper), to);
+			lower->destroy(lower);
+			upper->destroy(upper);
+		}
+	}
 	else
 	{
 		ts = traffic_selector_create_from_cidr(buf, proto, from, to);
@@ -948,9 +991,14 @@ CALLBACK(parse_auth, bool,
 	{
 		return FALSE;
 	}
-	if (strcaseeq(buf, "pubkey"))
+	if (strpfx(buf, "ike:") ||
+		strpfx(buf, "pubkey") ||
+		strpfx(buf, "rsa") ||
+		strpfx(buf, "ecdsa") ||
+		strpfx(buf, "bliss"))
 	{
 		cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+		cfg->add_pubkey_constraints(cfg, buf, TRUE);
 		return TRUE;
 	}
 	if (strcaseeq(buf, "psk"))
@@ -970,8 +1018,16 @@ CALLBACK(parse_auth, bool,
 	}
 	if (strcasepfx(buf, "eap"))
 	{
+		char *pos;
+
 		cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
 
+		pos = strchr(buf, ':');
+		if (pos)
+		{
+			*pos = 0;
+			cfg->add_pubkey_constraints(cfg, pos + 1, FALSE);
+		}
 		type = eap_vendor_type_from_string(buf);
 		if (type)
 		{
@@ -1053,6 +1109,7 @@ CALLBACK(parse_group, bool,
 static bool parse_cert(auth_data_t *auth, auth_rule_t rule, chunk_t v)
 {
 	vici_authority_t *authority;
+	vici_cred_t *cred;
 	certificate_t *cert;
 
 	cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
@@ -1064,6 +1121,8 @@ static bool parse_cert(auth_data_t *auth, auth_rule_t rule, chunk_t v)
 			authority = auth->request->this->authority;
 			authority->check_for_hash_and_url(authority, cert);
 		}
+		cred = auth->request->this->cred;
+		cert = cred->add_cert(cred, cert);
 		auth->cfg->add(auth->cfg, rule, cert);
 		return TRUE;
 	}
@@ -1089,6 +1148,27 @@ CALLBACK(parse_cacerts, bool,
 }
 
 /**
+ * Parse raw public keys
+ */
+CALLBACK(parse_pubkeys, bool,
+	auth_data_t *auth, chunk_t v)
+{
+	vici_cred_t *cred;
+	certificate_t *cert;
+
+	cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY,
+							  BUILD_BLOB_PEM, v, BUILD_END);
+	if (cert)
+	{
+		cred = auth->request->this->cred;
+		cert = cred->add_cert(cred, cert);
+		auth->cfg->add(auth->cfg, AUTH_RULE_SUBJECT_CERT, cert);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
  * Parse revocation status
  */
 CALLBACK(parse_revocation, bool,
@@ -1283,6 +1363,7 @@ CALLBACK(auth_li, bool,
 		{ "groups",			parse_group,		auth->cfg					},
 		{ "certs",			parse_certs,		auth						},
 		{ "cacerts",		parse_cacerts,		auth						},
+		{ "pubkeys",		parse_pubkeys,		auth						},
 	};
 
 	return parse_rules(rules, countof(rules), name, value,
@@ -1299,6 +1380,7 @@ CALLBACK(auth_kv, bool,
 		{ "eap_id",			parse_eap_id,		auth->cfg					},
 		{ "xauth_id",		parse_xauth_id,		auth->cfg					},
 		{ "revocation",		parse_revocation,	auth->cfg					},
+		{ "round",			parse_uint32,		&auth->round				},
 	};
 
 	return parse_rules(rules, countof(rules), name, value,
@@ -1502,40 +1584,62 @@ CALLBACK(peer_sn, bool,
 	if (strcasepfx(name, "local") ||
 		strcasepfx(name, "remote"))
 	{
-		auth_data_t auth = {
+		enumerator_t *enumerator;
+		linked_list_t *auths;
+		auth_data_t *auth, *current;
+		auth_rule_t rule;
+		certificate_t *cert;
+		pubkey_cert_t *pubkey_cert;
+		identification_t *id;
+		bool default_id = FALSE;
+
+		INIT(auth,
 			.request = peer->request,
 			.cfg = auth_cfg_create(),
-		};
+		);
 
-		if (!message->parse(message, ctx, NULL, auth_kv, auth_li, &auth))
+		if (!message->parse(message, ctx, NULL, auth_kv, auth_li, auth))
 		{
-			auth.cfg->destroy(auth.cfg);
+			free_auth_data(auth);
 			return FALSE;
 		}
+		id = auth->cfg->get(auth->cfg, AUTH_RULE_IDENTITY);
 
-		if (!auth.cfg->get(auth.cfg, AUTH_RULE_IDENTITY))
+		enumerator = auth->cfg->create_enumerator(auth->cfg);
+		while (enumerator->enumerate(enumerator, &rule, &cert))
 		{
-			identification_t *id;
-			certificate_t *cert;
-
-			cert = auth.cfg->get(auth.cfg, AUTH_RULE_SUBJECT_CERT);
-			if (cert)
+			if (rule == AUTH_RULE_SUBJECT_CERT && !default_id)
 			{
-				id = cert->get_subject(cert);
-				DBG1(DBG_CFG, "  id not specified, defaulting to cert id '%Y'",
-					 id);
-				auth.cfg->add(auth.cfg, AUTH_RULE_IDENTITY, id->clone(id));
+				if (id == NULL)
+				{
+					id = cert->get_subject(cert);
+					DBG1(DBG_CFG, "  id not specified, defaulting to"
+								  " cert subject '%Y'", id);
+					auth->cfg->add(auth->cfg, AUTH_RULE_IDENTITY, id->clone(id));
+					default_id = TRUE;
+				}
+				else if (cert->get_type(cert) == CERT_TRUSTED_PUBKEY &&
+						 id->get_type != ID_ANY)
+				{
+					/* set the subject of all raw public keys to the id */
+					pubkey_cert = (pubkey_cert_t*)cert;
+					pubkey_cert->set_subject(pubkey_cert, id);
+				}
 			}
 		}
+		enumerator->destroy(enumerator);
 
-		if (strcasepfx(name, "local"))
+		auths = strcasepfx(name, "local") ? peer->local : peer->remote;
+		enumerator = auths->create_enumerator(auths);
+		while (enumerator->enumerate(enumerator, &current))
 		{
-			peer->local->insert_last(peer->local, auth.cfg);
-		}
-		else
-		{
-			peer->remote->insert_last(peer->remote, auth.cfg);
+			if (auth->round < current->round)
+			{
+				break;
+			}
 		}
+		auths->insert_before(auths, enumerator, auth);
+		enumerator->destroy(enumerator);
 		return TRUE;
 	}
 	peer->request->reply = create_reply("invalid section: %s", name);
@@ -1578,7 +1682,7 @@ static u_int32_t find_reqid(child_cfg_t *cfg)
 }
 
 /**
- * Perform start actions associated to a child config
+ * Perform start actions associated with a child config
  */
 static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg,
 							 child_cfg_t *child_cfg)
@@ -1611,19 +1715,20 @@ static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg,
 }
 
 /**
- * Undo start actions associated to a child config
+ * Undo start actions associated with a child config
  */
-static void clear_start_action(private_vici_config_t *this,
+static void clear_start_action(private_vici_config_t *this, char *peer_name,
 							   child_cfg_t *child_cfg)
 {
 	enumerator_t *enumerator, *children;
 	child_sa_t *child_sa;
 	ike_sa_t *ike_sa;
-	u_int32_t id = 0, *del;
-	array_t *ids = NULL;
+	u_int32_t id = 0, others;
+	array_t *ids = NULL, *ikeids = NULL;
 	char *name;
 
 	name = child_cfg->get_name(child_cfg);
+
 	switch (child_cfg->get_start_action(child_cfg))
 	{
 		case ACTION_RESTART:
@@ -1631,29 +1736,72 @@ static void clear_start_action(private_vici_config_t *this,
 													charon->controller, TRUE);
 			while (enumerator->enumerate(enumerator, &ike_sa))
 			{
+				if (!streq(ike_sa->get_name(ike_sa), peer_name))
+				{
+					continue;
+				}
+				others = id = 0;
 				children = ike_sa->create_child_sa_enumerator(ike_sa);
 				while (children->enumerate(children, &child_sa))
 				{
-					if (streq(name, child_sa->get_name(child_sa)))
+					if (child_sa->get_state(child_sa) != CHILD_DELETING)
 					{
-						id = child_sa->get_unique_id(child_sa);
-						array_insert_create(&ids, ARRAY_TAIL, &id);
+						if (streq(name, child_sa->get_name(child_sa)))
+						{
+							id = child_sa->get_unique_id(child_sa);
+						}
+						else
+						{
+							others++;
+						}
 					}
 				}
 				children->destroy(children);
+
+				if (id && !others)
+				{
+					/* found matching children only, delete full IKE_SA */
+					id = ike_sa->get_unique_id(ike_sa);
+					array_insert_create_value(&ikeids, sizeof(id),
+											  ARRAY_TAIL, &id);
+				}
+				else
+				{
+					children = ike_sa->create_child_sa_enumerator(ike_sa);
+					while (children->enumerate(children, &child_sa))
+					{
+						if (streq(name, child_sa->get_name(child_sa)))
+						{
+							id = child_sa->get_unique_id(child_sa);
+							array_insert_create_value(&ids, sizeof(id),
+													  ARRAY_TAIL, &id);
+						}
+					}
+					children->destroy(children);
+				}
 			}
 			enumerator->destroy(enumerator);
 
 			if (array_count(ids))
 			{
-				while (array_remove(ids, ARRAY_HEAD, &del))
+				while (array_remove(ids, ARRAY_HEAD, &id))
 				{
-					DBG1(DBG_CFG, "closing '%s' #%u", name, *del);
+					DBG1(DBG_CFG, "closing '%s' #%u", name, id);
 					charon->controller->terminate_child(charon->controller,
-														*del, NULL, NULL, 0);
+														id, NULL, NULL, 0);
 				}
 				array_destroy(ids);
 			}
+			if (array_count(ikeids))
+			{
+				while (array_remove(ikeids, ARRAY_HEAD, &id))
+				{
+					DBG1(DBG_CFG, "closing IKE_SA #%u", id);
+					charon->controller->terminate_ike(charon->controller,
+													  id, NULL, NULL, 0);
+				}
+				array_destroy(ikeids);
+			}
 			break;
 		case ACTION_ROUTE:
 			DBG1(DBG_CFG, "uninstalling '%s'", name);
@@ -1687,36 +1835,56 @@ static void clear_start_action(private_vici_config_t *this,
 }
 
 /**
- * Run start actions associated to all child configs of a peer config
+ * Run or undo a start actions associated with a child config
  */
-static void run_start_actions(private_vici_config_t *this, peer_cfg_t *peer_cfg)
+static void handle_start_action(private_vici_config_t *this,
+								peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
+								bool undo)
 {
-	enumerator_t *enumerator;
-	child_cfg_t *child_cfg;
+	this->handling_actions = TRUE;
+	this->lock->unlock(this->lock);
 
-	enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
-	while (enumerator->enumerate(enumerator, &child_cfg))
+	if (undo)
+	{
+		clear_start_action(this, peer_cfg->get_name(peer_cfg), child_cfg);
+	}
+	else
 	{
 		run_start_action(this, peer_cfg, child_cfg);
 	}
-	enumerator->destroy(enumerator);
+
+	this->lock->write_lock(this->lock);
+	this->handling_actions = FALSE;
 }
 
 /**
- * Undo start actions associated to all child configs of a peer config
+ * Run or undo start actions associated with all child configs of a peer config
  */
-static void clear_start_actions(private_vici_config_t *this,
-								peer_cfg_t *peer_cfg)
+static void handle_start_actions(private_vici_config_t *this,
+								 peer_cfg_t *peer_cfg, bool undo)
 {
 	enumerator_t *enumerator;
 	child_cfg_t *child_cfg;
 
+	this->handling_actions = TRUE;
+	this->lock->unlock(this->lock);
+
 	enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
 	while (enumerator->enumerate(enumerator, &child_cfg))
 	{
-		clear_start_action(this, child_cfg);
+		if (undo)
+		{
+			clear_start_action(this, peer_cfg->get_name(peer_cfg), child_cfg);
+		}
+		else
+		{
+			run_start_action(this, peer_cfg, child_cfg);
+		}
 	}
 	enumerator->destroy(enumerator);
+
+	this->lock->write_lock(this->lock);
+	this->handling_actions = FALSE;
 }
 
 /**
@@ -1727,22 +1895,12 @@ static void replace_children(private_vici_config_t *this,
 {
 	enumerator_t *enumerator;
 	child_cfg_t *child;
+	bool added;
 
-	enumerator = to->create_child_cfg_enumerator(to);
-	while (enumerator->enumerate(enumerator, &child))
+	enumerator = to->replace_child_cfgs(to, from);
+	while (enumerator->enumerate(enumerator, &child, &added))
 	{
-		to->remove_child_cfg(to, enumerator);
-		clear_start_action(this, child);
-		child->destroy(child);
-	}
-	enumerator->destroy(enumerator);
-
-	enumerator = from->create_child_cfg_enumerator(from);
-	while (enumerator->enumerate(enumerator, &child))
-	{
-		from->remove_child_cfg(from, enumerator);
-		to->add_child_cfg(to, child);
-		run_start_action(this, to, child);
+		handle_start_action(this, to, child, !added);
 	}
 	enumerator->destroy(enumerator);
 }
@@ -1758,6 +1916,10 @@ static void merge_config(private_vici_config_t *this, peer_cfg_t *peer_cfg)
 	bool merged = FALSE;
 
 	this->lock->write_lock(this->lock);
+	while (this->handling_actions)
+	{
+		this->condvar->wait(this->condvar, this->lock);
+	}
 
 	enumerator = this->conns->create_enumerator(this->conns);
 	while (enumerator->enumerate(enumerator, &current))
@@ -1778,10 +1940,10 @@ static void merge_config(private_vici_config_t *this, peer_cfg_t *peer_cfg)
 				DBG1(DBG_CFG, "replaced vici connection: %s",
 					 peer_cfg->get_name(peer_cfg));
 				this->conns->remove_at(this->conns, enumerator);
-				clear_start_actions(this, current);
-				current->destroy(current);
 				this->conns->insert_last(this->conns, peer_cfg);
-				run_start_actions(this, peer_cfg);
+				handle_start_actions(this, current, TRUE);
+				handle_start_actions(this, peer_cfg, FALSE);
+				current->destroy(current);
 			}
 			merged = TRUE;
 			break;
@@ -1793,9 +1955,9 @@ static void merge_config(private_vici_config_t *this, peer_cfg_t *peer_cfg)
 	{
 		DBG1(DBG_CFG, "added vici connection: %s", peer_cfg->get_name(peer_cfg));
 		this->conns->insert_last(this->conns, peer_cfg);
-		run_start_actions(this, peer_cfg);
+		handle_start_actions(this, peer_cfg, FALSE);
 	}
-
+	this->condvar->signal(this->condvar);
 	this->lock->unlock(this->lock);
 }
 
@@ -1828,7 +1990,7 @@ CALLBACK(config_sn, bool,
 	peer_cfg_t *peer_cfg;
 	ike_cfg_t *ike_cfg;
 	child_cfg_t *child_cfg;
-	auth_cfg_t *auth_cfg;
+	auth_data_t *auth;
 	proposal_t *proposal;
 	host_t *host;
 	char *str;
@@ -1843,14 +2005,17 @@ CALLBACK(config_sn, bool,
 
 	if (peer.local->get_count(peer.local) == 0)
 	{
-		free_peer_data(&peer);
-		peer.request->reply = create_reply("missing local auth config");
-		return FALSE;
+		INIT(auth,
+			.cfg = auth_cfg_create(),
+		);
+		peer.local->insert_last(peer.local, auth);
 	}
 	if (peer.remote->get_count(peer.remote) == 0)
 	{
-		auth_cfg = auth_cfg_create();
-		peer.remote->insert_last(peer.remote, auth_cfg);
+		INIT(auth,
+			.cfg = auth_cfg_create(),
+		);
+		peer.remote->insert_last(peer.remote, auth);
 	}
 	if (peer.proposals->get_count(peer.proposals) == 0)
 	{
@@ -1926,14 +2091,18 @@ CALLBACK(config_sn, bool,
 						FALSE, NULL, NULL);
 
 	while (peer.local->remove_first(peer.local,
-									(void**)&auth_cfg) == SUCCESS)
+									(void**)&auth) == SUCCESS)
 	{
-		peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
+		peer_cfg->add_auth_cfg(peer_cfg, auth->cfg, TRUE);
+		auth->cfg = NULL;
+		free_auth_data(auth);
 	}
 	while (peer.remote->remove_first(peer.remote,
-									 (void**)&auth_cfg) == SUCCESS)
+									 (void**)&auth) == SUCCESS)
 	{
-		peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
+		peer_cfg->add_auth_cfg(peer_cfg, auth->cfg, FALSE);
+		auth->cfg = NULL;
+		free_auth_data(auth);
 	}
 	while (peer.children->remove_first(peer.children,
 									   (void**)&child_cfg) == SUCCESS)
@@ -1999,18 +2168,24 @@ CALLBACK(unload_conn, vici_message_t*,
 	}
 
 	this->lock->write_lock(this->lock);
+	while (this->handling_actions)
+	{
+		this->condvar->wait(this->condvar, this->lock);
+	}
 	enumerator = this->conns->create_enumerator(this->conns);
 	while (enumerator->enumerate(enumerator, &cfg))
 	{
 		if (streq(cfg->get_name(cfg), conn_name))
 		{
 			this->conns->remove_at(this->conns, enumerator);
+			handle_start_actions(this, cfg, TRUE);
 			cfg->destroy(cfg);
 			found = TRUE;
 			break;
 		}
 	}
 	enumerator->destroy(enumerator);
+	this->condvar->signal(this->condvar);
 	this->lock->unlock(this->lock);
 
 	if (!found)
@@ -2066,6 +2241,7 @@ METHOD(vici_config_t, destroy, void,
 {
 	manage_commands(this, FALSE);
 	this->conns->destroy_offset(this->conns, offsetof(peer_cfg_t, destroy));
+	this->condvar->destroy(this->condvar);
 	this->lock->destroy(this->lock);
 	free(this);
 }
@@ -2074,7 +2250,8 @@ METHOD(vici_config_t, destroy, void,
  * See header
  */
 vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher,
-								  vici_authority_t *authority)
+								  vici_authority_t *authority,
+								  vici_cred_t *cred)
 {
 	private_vici_config_t *this;
 
@@ -2090,7 +2267,9 @@ vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher,
 		.dispatcher = dispatcher,
 		.conns = linked_list_create(),
 		.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+		.condvar = rwlock_condvar_create(),
 		.authority = authority,
+		.cred = cred,
 	);
 
 	manage_commands(this, TRUE);
diff --git a/src/libcharon/plugins/vici/vici_config.h b/src/libcharon/plugins/vici/vici_config.h
index c3245bf..0c237e7 100644
--- a/src/libcharon/plugins/vici/vici_config.h
+++ b/src/libcharon/plugins/vici/vici_config.h
@@ -26,6 +26,7 @@
 
 #include "vici_dispatcher.h"
 #include "vici_authority.h"
+#include "vici_cred.h"
 
 #include <config/backend.h>
 
@@ -51,9 +52,11 @@ struct vici_config_t {
  *
  * @param dispatcher		dispatcher to receive requests from
  * @param authority			Auxiliary certification authority information
+ * @param cred				in-memory credential backend managed by VICI
  * @return					config backend
  */
 vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher,
-								  vici_authority_t *authority);
+								  vici_authority_t *authority,
+								  vici_cred_t *cred);
 
 #endif /** VICI_CONFIG_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_control.c b/src/libcharon/plugins/vici/vici_control.c
index 752007c..c526d2f 100644
--- a/src/libcharon/plugins/vici/vici_control.c
+++ b/src/libcharon/plugins/vici/vici_control.c
@@ -1,4 +1,7 @@
 /*
+ * Copyright (C) 2015 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
  * Copyright (C) 2014 Martin Willi
  * Copyright (C) 2014 revosec AG
  *
@@ -20,6 +23,7 @@
 
 #include <daemon.h>
 #include <collections/array.h>
+#include <processing/jobs/redirect_job.h>
 
 typedef struct private_vici_control_t private_vici_control_t;
 
@@ -134,7 +138,7 @@ static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name)
 /**
  * Find a peer/child config from a child config name
  */
-static child_cfg_t* find_child_cfg(char *name, peer_cfg_t **out)
+static child_cfg_t* find_child_cfg(char *name, char *pname, peer_cfg_t **out)
 {
 	enumerator_t *enumerator;
 	peer_cfg_t *peer_cfg;
@@ -144,6 +148,10 @@ static child_cfg_t* find_child_cfg(char *name, peer_cfg_t **out)
 							charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
 	while (enumerator->enumerate(enumerator, &peer_cfg))
 	{
+		if (pname && !streq(pname, peer_cfg->get_name(peer_cfg)))
+		{
+			continue;
+		}
 		child_cfg = get_child_from_peer(peer_cfg, name);
 		if (child_cfg)
 		{
@@ -161,15 +169,17 @@ CALLBACK(initiate, vici_message_t*,
 {
 	child_cfg_t *child_cfg = NULL;
 	peer_cfg_t *peer_cfg;
-	char *child;
-	u_int timeout;
+	char *child, *ike;
+	int timeout;
 	bool limits;
+	controller_cb_t log_cb = NULL;
 	log_info_t log = {
 		.dispatcher = this->dispatcher,
 		.id = id,
 	};
 
 	child = request->get_str(request, NULL, "child");
+	ike = request->get_str(request, NULL, "ike");
 	timeout = request->get_int(request, 0, "timeout");
 	limits = request->get_bool(request, FALSE, "init-limits");
 	log.level = request->get_int(request, 1, "loglevel");
@@ -178,16 +188,20 @@ CALLBACK(initiate, vici_message_t*,
 	{
 		return send_reply(this, "missing configuration name");
 	}
+	if (timeout >= 0)
+	{
+		log_cb = (controller_cb_t)log_vici;
+	}
 
 	DBG1(DBG_CFG, "vici initiate '%s'", child);
 
-	child_cfg = find_child_cfg(child, &peer_cfg);
+	child_cfg = find_child_cfg(child, ike, &peer_cfg);
 	if (!child_cfg)
 	{
 		return send_reply(this, "CHILD_SA config '%s' not found", child);
 	}
 	switch (charon->controller->initiate(charon->controller, peer_cfg,
-				child_cfg, (controller_cb_t)log_vici, &log, timeout, limits))
+									child_cfg, log_cb, &log, timeout, limits))
 	{
 		case SUCCESS:
 			return send_reply(this, NULL);
@@ -208,11 +222,13 @@ CALLBACK(terminate, vici_message_t*,
 {
 	enumerator_t *enumerator, *isas, *csas;
 	char *child, *ike, *errmsg = NULL;
-	u_int timeout, child_id, ike_id, current, *del, done = 0;
+	u_int child_id, ike_id, current, *del, done = 0;
+	int timeout;
 	ike_sa_t *ike_sa;
 	child_sa_t *child_sa;
 	array_t *ids;
 	vici_builder_t *builder;
+	controller_cb_t log_cb = NULL;
 	log_info_t log = {
 		.dispatcher = this->dispatcher,
 		.id = id,
@@ -247,6 +263,11 @@ CALLBACK(terminate, vici_message_t*,
 		DBG1(DBG_CFG, "vici terminate CHILD_SA '%s'", child);
 	}
 
+	if (timeout >= 0)
+	{
+		log_cb = (controller_cb_t)log_vici;
+	}
+
 	ids = array_create(sizeof(u_int), 0);
 
 	isas = charon->controller->create_ike_sa_enumerator(charon->controller, TRUE);
@@ -296,7 +317,7 @@ CALLBACK(terminate, vici_message_t*,
 		if (child || child_id)
 		{
 			if (charon->controller->terminate_child(charon->controller, *del,
-						(controller_cb_t)log_vici, &log, timeout) == SUCCESS)
+											log_cb, &log, timeout) == SUCCESS)
 			{
 				done++;
 			}
@@ -304,7 +325,7 @@ CALLBACK(terminate, vici_message_t*,
 		else
 		{
 			if (charon->controller->terminate_ike(charon->controller, *del,
-						(controller_cb_t)log_vici, &log, timeout) == SUCCESS)
+											log_cb, &log, timeout) == SUCCESS)
 			{
 				done++;
 			}
@@ -340,6 +361,150 @@ CALLBACK(terminate, vici_message_t*,
 }
 
 /**
+ * Parse a peer-ip specified, which can be a subnet in CIDR notation, a range
+ * or a single IP address.
+ */
+static traffic_selector_t *parse_peer_ip(char *ip)
+{
+	traffic_selector_t *ts;
+	host_t *from, *to;
+	ts_type_t type;
+
+	if (host_create_from_range(ip, &from, &to))
+	{
+		if (to->get_family(to) == AF_INET)
+		{
+			type = TS_IPV4_ADDR_RANGE;
+		}
+		else
+		{
+			type = TS_IPV6_ADDR_RANGE;
+		}
+		ts = traffic_selector_create_from_bytes(0, type,
+												from->get_address(from), 0,
+												to->get_address(to), 0xFFFF);
+		from->destroy(from);
+		to->destroy(to);
+		return ts;
+	}
+	return traffic_selector_create_from_cidr(ip, 0, 0, 0xFFFF);
+}
+
+CALLBACK(redirect, vici_message_t*,
+	private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
+{
+	enumerator_t *sas;
+	char *ike, *peer_ip, *peer_id, *gw, *errmsg = NULL;
+	u_int ike_id, current, found = 0;
+	identification_t *gateway, *identity = NULL, *other_id;
+	traffic_selector_t *ts = NULL;
+	ike_sa_t *ike_sa;
+	vici_builder_t *builder;
+
+	ike = request->get_str(request, NULL, "ike");
+	ike_id = request->get_int(request, 0, "ike-id");
+	peer_ip = request->get_str(request, NULL, "peer-ip");
+	peer_id = request->get_str(request, NULL, "peer-id");
+	gw = request->get_str(request, NULL, "gateway");
+
+	if (!gw || !(gateway = identification_create_from_string(gw)))
+	{
+		return send_reply(this, "missing target gateway");
+	}
+	switch (gateway->get_type(gateway))
+	{
+		case ID_IPV4_ADDR:
+		case ID_IPV6_ADDR:
+		case ID_FQDN:
+			break;
+		default:
+			return send_reply(this, "unsupported gateway identity");
+	}
+	if (peer_ip)
+	{
+		ts = parse_peer_ip(peer_ip);
+		if (!ts)
+		{
+			return send_reply(this, "invalid peer IP selector");
+		}
+		DBG1(DBG_CFG, "vici redirect IKE_SAs with src %R to %Y", ts,
+			 gateway);
+	}
+	if (peer_id)
+	{
+		identity = identification_create_from_string(peer_id);
+		if (!identity)
+		{
+			DESTROY_IF(ts);
+			return send_reply(this, "invalid peer identity selector");
+		}
+		DBG1(DBG_CFG, "vici redirect IKE_SAs with ID '%Y' to %Y", identity,
+			 gateway);
+	}
+	if (ike_id)
+	{
+		DBG1(DBG_CFG, "vici redirect IKE_SA #%d to '%Y'", ike_id, gateway);
+	}
+	if (ike)
+	{
+		DBG1(DBG_CFG, "vici redirect IKE_SA '%s' to '%Y'", ike, gateway);
+	}
+	if (!peer_ip && !peer_id && !ike && !ike_id)
+	{
+		return send_reply(this, "missing redirect selector");
+	}
+
+	sas = charon->controller->create_ike_sa_enumerator(charon->controller, TRUE);
+	while (sas->enumerate(sas, &ike_sa))
+	{
+		if (ike_sa->get_version(ike_sa) != IKEV2)
+		{
+			continue;
+		}
+		current = ike_sa->get_unique_id(ike_sa);
+		if (ike_id && ike_id != current)
+		{
+			continue;
+		}
+		if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
+		{
+			continue;
+		}
+		if (ts && !ts->includes(ts, ike_sa->get_other_host(ike_sa)))
+		{
+			continue;
+		}
+		if (identity)
+		{
+			other_id = ike_sa->get_other_eap_id(ike_sa);
+			if (!other_id->matches(other_id, identity))
+			{
+				continue;
+			}
+		}
+		lib->processor->queue_job(lib->processor,
+				(job_t*)redirect_job_create(ike_sa->get_id(ike_sa), gateway));
+		found++;
+	}
+	sas->destroy(sas);
+
+	builder = vici_builder_create();
+	if (!found)
+	{
+		errmsg = "no matching SAs to redirect found";
+	}
+	builder->add_kv(builder, "success", errmsg ? "no" : "yes");
+	if (errmsg)
+	{
+		builder->add_kv(builder, "errmsg", "%s", errmsg);
+	}
+	gateway->destroy(gateway);
+	DESTROY_IF(identity);
+	DESTROY_IF(ts);
+	return builder->finalize(builder);
+}
+
+/**
  * Find reqid of an existing CHILD_SA
  */
 static u_int32_t find_reqid(child_cfg_t *cfg)
@@ -379,10 +544,11 @@ CALLBACK(install, vici_message_t*,
 {
 	child_cfg_t *child_cfg = NULL;
 	peer_cfg_t *peer_cfg;
-	char *child;
+	char *child, *ike;
 	bool ok;
 
 	child = request->get_str(request, NULL, "child");
+	ike = request->get_str(request, NULL, "ike");
 	if (!child)
 	{
 		return send_reply(this, "missing configuration name");
@@ -390,7 +556,7 @@ CALLBACK(install, vici_message_t*,
 
 	DBG1(DBG_CFG, "vici install '%s'", child);
 
-	child_cfg = find_child_cfg(child, &peer_cfg);
+	child_cfg = find_child_cfg(child, ike, &peer_cfg);
 	if (!child_cfg)
 	{
 		return send_reply(this, "configuration name not found");
@@ -480,6 +646,7 @@ static void manage_commands(private_vici_control_t *this, bool reg)
 {
 	manage_command(this, "initiate", initiate, reg);
 	manage_command(this, "terminate", terminate, reg);
+	manage_command(this, "redirect", redirect, reg);
 	manage_command(this, "install", install, reg);
 	manage_command(this, "uninstall", uninstall, reg);
 	manage_command(this, "reload-settings", reload_settings, reg);
diff --git a/src/libcharon/plugins/vici/vici_cred.c b/src/libcharon/plugins/vici/vici_cred.c
index 6631184..3411b7d 100644
--- a/src/libcharon/plugins/vici/vici_cred.c
+++ b/src/libcharon/plugins/vici/vici_cred.c
@@ -2,6 +2,9 @@
  * Copyright (C) 2014 Martin Willi
  * Copyright (C) 2014 revosec AG
  *
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR 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
@@ -15,6 +18,7 @@
 
 #include "vici_cred.h"
 #include "vici_builder.h"
+#include "vici_cert_info.h"
 
 #include <credentials/sets/mem_cred.h>
 #include <credentials/certificates/ac.h>
@@ -66,9 +70,9 @@ static vici_message_t* create_reply(char *fmt, ...)
 CALLBACK(load_cert, vici_message_t*,
 	private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
 {
-	certificate_type_t type;
-	x509_flag_t required_flags = 0, additional_flags = 0;
 	certificate_t *cert;
+	certificate_type_t type;
+	x509_flag_t ext_flag, flag = X509_NONE;
 	x509_t *x509;
 	chunk_t data;
 	bool trusted = TRUE;
@@ -79,60 +83,55 @@ CALLBACK(load_cert, vici_message_t*,
 	{
 		return create_reply("certificate type missing");
 	}
-	if (strcaseeq(str, "x509"))
-	{
-		type = CERT_X509;
-	}
-	else if (strcaseeq(str, "x509ca"))
-	{
-		type = CERT_X509;
-		required_flags = X509_CA;
-	}
-	else if (strcaseeq(str, "x509aa"))
-	{
-		type = CERT_X509;
-		additional_flags = X509_AA;
-	}
-	else if (strcaseeq(str, "x509crl"))
+	if (enum_from_name(certificate_type_names, str, &type))
 	{
-		type = CERT_X509_CRL;
-	}
-	else if (strcaseeq(str, "x509ac"))
-	{
-		type = CERT_X509_AC;
-		trusted = FALSE;
+		if (type == CERT_X509)
+		{
+			str = message->get_str(message, "NONE", "flag");
+			if (!enum_from_name(x509_flag_names, str, &flag))
+			{
+				return create_reply("invalid certificate flag '%s'", str);
+			}
+		}
 	}
-	else
+	else if	(!vici_cert_info_from_str(str, &type, &flag))
 	{
-		return create_reply("invalid certificate type: %s", str);
+		return create_reply("invalid certificate type '%s'", str);
 	}
+
 	data = message->get_value(message, chunk_empty, "data");
 	if (!data.len)
 	{
 		return create_reply("certificate data missing");
 	}
+
+	/* do not set CA flag externally */
+	ext_flag = (flag & X509_CA) ? X509_NONE : flag;
+
 	cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
 							  BUILD_BLOB_PEM, data,
-							  BUILD_X509_FLAG, additional_flags,
+							  BUILD_X509_FLAG, ext_flag,
 							  BUILD_END);
 	if (!cert)
 	{
 		return create_reply("parsing %N certificate failed",
 							certificate_type_names, type);
 	}
-	if (cert->get_type(cert) == CERT_X509)
+	DBG1(DBG_CFG, "loaded certificate '%Y'", cert->get_subject(cert));
+
+	/* check if CA certificate has CA basic constraint set */
+	if (flag & X509_CA)
 	{
+		char err_msg[] = "ca certificate lacks CA basic constraint, rejected";
 		x509 = (x509_t*)cert;
 
-		if ((required_flags & x509->get_flags(x509)) != required_flags)
+		if (!(x509->get_flags(x509) & X509_CA))
 		{
 			cert->destroy(cert);
-			return create_reply("certificate misses required flag, rejected");
+			DBG1(DBG_CFG, "  %s", err_msg);
+			return create_reply(err_msg);
 		}
 	}
-
-	DBG1(DBG_CFG, "loaded certificate '%Y'", cert->get_subject(cert));
-
 	if (type == CERT_X509_CRL)
 	{
 		this->creds->add_crl(this->creds, (crl_t*)cert);
@@ -169,6 +168,10 @@ CALLBACK(load_key, vici_message_t*,
 	{
 		type = KEY_ECDSA;
 	}
+	else if (strcaseeq(str, "bliss"))
+	{
+		type = KEY_BLISS;
+	}
 	else
 	{
 		return create_reply("invalid key type: %s", str);
@@ -305,7 +308,7 @@ static void manage_commands(private_vici_cred_t *this, bool reg)
 METHOD(vici_cred_t, add_cert, certificate_t*,
 	private_vici_cred_t *this, certificate_t *cert)
 {
-	return this->creds->get_cert_ref(this->creds, cert);
+	return this->creds->add_cert_ref(this->creds, TRUE, cert);
 }
 
 METHOD(vici_cred_t, destroy, void,
diff --git a/src/libcharon/plugins/vici/vici_plugin.c b/src/libcharon/plugins/vici/vici_plugin.c
index 53ed8cd..ed7c743 100644
--- a/src/libcharon/plugins/vici/vici_plugin.c
+++ b/src/libcharon/plugins/vici/vici_plugin.c
@@ -131,7 +131,8 @@ static bool register_vici(private_vici_plugin_t *this,
 			this->authority = vici_authority_create(this->dispatcher,
 													this->cred);
 			lib->credmgr->add_set(lib->credmgr, &this->authority->set);
-			this->config = vici_config_create(this->dispatcher, this->authority);
+			this->config = vici_config_create(this->dispatcher, this->authority,
+											  this->cred);
 			this->attrs = vici_attribute_create(this->dispatcher);
 			this->logger = vici_logger_create(this->dispatcher);
 
diff --git a/src/libcharon/plugins/vici/vici_query.c b/src/libcharon/plugins/vici/vici_query.c
index 9a3d832..284c23e 100644
--- a/src/libcharon/plugins/vici/vici_query.c
+++ b/src/libcharon/plugins/vici/vici_query.c
@@ -1,4 +1,7 @@
 /*
+ * Copyright (C) 2015 Tobias Brunner, Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
  * Copyright (C) 2014 Martin Willi
  * Copyright (C) 2014 revosec AG
  *
@@ -37,6 +40,7 @@
 
 #include "vici_query.h"
 #include "vici_builder.h"
+#include "vici_cert_info.h"
 
 #include <inttypes.h>
 #include <time.h>
@@ -48,6 +52,9 @@
 #endif
 
 #include <daemon.h>
+#include <asn1/asn1.h>
+#include <credentials/certificates/certificate.h>
+#include <credentials/certificates/x509.h>
 
 typedef struct private_vici_query_t private_vici_query_t;
 
@@ -120,7 +127,7 @@ static void list_child(private_vici_query_t *this, vici_builder_t *b,
 				}
 			}
 			if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
-										&alg, &ks) && alg != ENCR_UNDEFINED)
+										&alg, &ks) && alg != AUTH_UNDEFINED)
 			{
 				b->add_kv(b, "integ-alg", "%N", integrity_algorithm_names, alg);
 				if (ks)
@@ -128,11 +135,6 @@ static void list_child(private_vici_query_t *this, vici_builder_t *b,
 					b->add_kv(b, "integ-keysize", "%u", ks);
 				}
 			}
-			if (proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION,
-										&alg, NULL))
-			{
-				b->add_kv(b, "prf-alg", "%N", pseudo_random_function_names, alg);
-			}
 			if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
 										&alg, NULL))
 			{
@@ -271,15 +273,20 @@ static void list_ike(private_vici_query_t *this, vici_builder_t *b,
 	identification_t *eap;
 	proposal_t *proposal;
 	u_int16_t alg, ks;
+	host_t *host;
 
 	b->add_kv(b, "uniqueid", "%u", ike_sa->get_unique_id(ike_sa));
 	b->add_kv(b, "version", "%u", ike_sa->get_version(ike_sa));
 	b->add_kv(b, "state", "%N", ike_sa_state_names, ike_sa->get_state(ike_sa));
 
-	b->add_kv(b, "local-host", "%H", ike_sa->get_my_host(ike_sa));
+	host = ike_sa->get_my_host(ike_sa);
+	b->add_kv(b, "local-host", "%H", host);
+	b->add_kv(b, "local-port", "%d", host->get_port(host));
 	b->add_kv(b, "local-id", "%Y", ike_sa->get_my_id(ike_sa));
 
-	b->add_kv(b, "remote-host", "%H", ike_sa->get_other_host(ike_sa));
+	host = ike_sa->get_other_host(ike_sa);
+	b->add_kv(b, "remote-host", "%H", host);
+	b->add_kv(b, "remote-port", "%d", host->get_port(host));
 	b->add_kv(b, "remote-id", "%Y", ike_sa->get_other_id(ike_sa));
 
 	eap = ike_sa->get_other_eap_id(ike_sa);
@@ -301,8 +308,10 @@ static void list_ike(private_vici_query_t *this, vici_builder_t *b,
 	{
 		b->add_kv(b, "initiator", "yes");
 	}
-	b->add_kv(b, "initiator-spi", "%.16"PRIx64, id->get_initiator_spi(id));
-	b->add_kv(b, "responder-spi", "%.16"PRIx64, id->get_responder_spi(id));
+	b->add_kv(b, "initiator-spi", "%.16"PRIx64,
+			  be64toh(id->get_initiator_spi(id)));
+	b->add_kv(b, "responder-spi", "%.16"PRIx64,
+			  be64toh(id->get_responder_spi(id)));
 
 	add_condition(b, ike_sa, "nat-local", COND_NAT_HERE);
 	add_condition(b, ike_sa, "nat-remote", COND_NAT_THERE);
@@ -772,7 +781,7 @@ CALLBACK(list_conns, vici_message_t*,
 /**
  * Do we have a private key for given certificate
  */
-static bool has_privkey(private_vici_query_t *this, certificate_t *cert)
+static bool has_privkey(certificate_t *cert)
 {
 	private_key_t *private;
 	public_key_t *public;
@@ -800,81 +809,332 @@ static bool has_privkey(private_vici_query_t *this, certificate_t *cert)
 	return found;
 }
 
-CALLBACK(list_certs, vici_message_t*,
-	private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
+/**
+ * Store cert filter data
+ */
+typedef struct {
+	certificate_type_t type;
+	x509_flag_t flag;
+	identification_t *subject;
+} cert_filter_t;
+
+/**
+ * Enumerate all X.509 certificates with a given flag
+ */
+static void enum_x509(private_vici_query_t *this, u_int id,
+					  linked_list_t *certs, cert_filter_t *filter,
+					  x509_flag_t flag)
 {
-	enumerator_t *enumerator, *added;
-	linked_list_t *list;
-	certificate_t *cert, *current;
-	chunk_t encoding;
-	identification_t *subject = NULL;
-	int type;
+	enumerator_t *enumerator;
+	certificate_t *cert;
 	vici_builder_t *b;
-	bool found;
-	char *str;
+	chunk_t encoding;
+	x509_t *x509;
 
-	str = request->get_str(request, "ANY", "type");
-	if (!enum_from_name(certificate_type_names, str, &type))
+	if (filter->type != CERT_ANY && filter->flag != X509_ANY &&
+		filter->flag != flag)
 	{
-		b = vici_builder_create();
-		return b->finalize(b);
-	}
-	str = request->get_str(request, NULL, "subject");
-	if (str)
-	{
-		subject = identification_create_from_string(str);
+		return;
 	}
 
-	list = linked_list_create();
-	enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
-												type, KEY_ANY, subject, FALSE);
+	enumerator = certs->create_enumerator(certs);
 	while (enumerator->enumerate(enumerator, &cert))
 	{
-		found = FALSE;
-		added = list->create_enumerator(list);
-		while (added->enumerate(added, &current))
+		x509 = (x509_t*)cert;
+		if ((x509->get_flags(x509) & X509_ANY) != flag)
 		{
-			if (current->equals(current, cert))
+			continue;
+		}
+
+		if (cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
+		{
+			b = vici_builder_create();
+			b->add_kv(b, "type", "%N", certificate_type_names, CERT_X509);
+			b->add_kv(b, "flag", "%N", x509_flag_names, flag);
+			if (has_privkey(cert))
 			{
-				found = TRUE;
-				break;
+				b->add_kv(b, "has_privkey", "yes");
 			}
+			b->add(b, VICI_KEY_VALUE, "data", encoding);
+			free(encoding.ptr);
+
+			this->dispatcher->raise_event(this->dispatcher, "list-cert", id,
+										  b->finalize(b));
 		}
-		added->destroy(added);
+	}
+	enumerator->destroy(enumerator);
+}
+
+/**
+ * Enumerate all non-X.509 certificate types
+ */
+static void enum_others(private_vici_query_t *this, u_int id,
+						linked_list_t *certs, certificate_type_t type)
+{
+	enumerator_t *enumerator;
+	certificate_t *cert;
+	vici_builder_t *b;
+	chunk_t encoding, t_ch;
+	cred_encoding_type_t encoding_type;
+	identification_t *subject;
+	time_t not_before, not_after;
+
+	encoding_type = (type == CERT_TRUSTED_PUBKEY) ? PUBKEY_SPKI_ASN1_DER :
+													CERT_ASN1_DER;
 
-		if (!found && cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
+	enumerator = certs->create_enumerator(certs);
+	while (enumerator->enumerate(enumerator, &cert))
+	{
+		if (cert->get_encoding(cert, encoding_type, &encoding))
 		{
 			b = vici_builder_create();
-			b->add_kv(b, "type", "%N",
-					  certificate_type_names, cert->get_type(cert));
-			if (has_privkey(this, cert))
+			b->add_kv(b, "type", "%N", certificate_type_names, type);
+			if (has_privkey(cert))
 			{
 				b->add_kv(b, "has_privkey", "yes");
 			}
 			b->add(b, VICI_KEY_VALUE, "data", encoding);
 			free(encoding.ptr);
 
+			if (type == CERT_TRUSTED_PUBKEY)
+			{
+				subject = cert->get_subject(cert);
+				if (subject->get_type(subject) != ID_KEY_ID)
+				{
+					b->add_kv(b, "subject", "%Y", cert->get_subject(cert));
+				}
+				cert->get_validity(cert, NULL, &not_before, &not_after);
+				if (not_before != UNDEFINED_TIME)
+				{
+					t_ch = asn1_from_time(&not_before, ASN1_GENERALIZEDTIME);
+					b->add(b, VICI_KEY_VALUE, "not-before", chunk_skip(t_ch, 2));
+					chunk_free(&t_ch);
+				}
+				if (not_after != UNDEFINED_TIME)
+				{
+					t_ch = asn1_from_time(&not_after, ASN1_GENERALIZEDTIME);
+					b->add(b, VICI_KEY_VALUE, "not-after", chunk_skip(t_ch, 2));
+					chunk_free(&t_ch);
+				}
+			}
 			this->dispatcher->raise_event(this->dispatcher, "list-cert", id,
 										  b->finalize(b));
-			list->insert_last(list, cert->get_ref(cert));
 		}
 	}
 	enumerator->destroy(enumerator);
+}
 
-	list->destroy_offset(list, offsetof(certificate_t, destroy));
-	DESTROY_IF(subject);
+/**
+ * Enumerate all certificates of a given type
+ */
+static void enum_certs(private_vici_query_t *this,	u_int id,
+					   cert_filter_t *filter, certificate_type_t type)
+{
+	enumerator_t *e1, *e2;
+	certificate_t *cert, *current;
+	linked_list_t *certs;
+	bool found;
 
+	if (filter->type != CERT_ANY && filter->type != type)
+	{
+		return;
+	}
+	certs = linked_list_create();
+
+	e1 = lib->credmgr->create_cert_enumerator(lib->credmgr, type, KEY_ANY,
+											  filter->subject, FALSE);
+	while (e1->enumerate(e1, &cert))
+	{
+		found = FALSE;
+
+		e2 = certs->create_enumerator(certs);
+		while (e2->enumerate(e2, &current))
+		{
+			if (current->equals(current, cert))
+			{
+				found = TRUE;
+				break;
+			}
+		}
+		e2->destroy(e2);
+
+		if (!found)
+		{
+			certs->insert_last(certs, cert->get_ref(cert));
+		}
+	}
+	e1->destroy(e1);
+
+	if (type == CERT_X509)
+	{
+		enum_x509(this, id, certs, filter, X509_NONE);
+		enum_x509(this, id, certs, filter, X509_CA);
+		enum_x509(this, id, certs, filter, X509_AA);
+		enum_x509(this, id, certs, filter, X509_OCSP_SIGNER);
+	}
+	else
+	{
+		enum_others(this, id, certs, type);
+	}
+	certs->destroy_offset(certs, offsetof(certificate_t, destroy));
+}
+
+CALLBACK(list_certs, vici_message_t*,
+	private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
+{
+	cert_filter_t filter = {
+		.type = CERT_ANY,
+		.flag = X509_ANY,
+		.subject = NULL
+	};
+	vici_builder_t *b;
+	char *str;
+
+	str = request->get_str(request, "ANY", "type");
+	if (enum_from_name(certificate_type_names, str, &filter.type))
+	{
+		if (filter.type == CERT_X509)
+		{
+			str = request->get_str(request, "ANY", "flag");
+			if (!enum_from_name(x509_flag_names, str, &filter.flag))
+			{
+				DBG1(DBG_CFG, "invalid certificate flag '%s'", str);
+				goto finalize;
+			}
+		}
+	}
+	else if	(!vici_cert_info_from_str(str, &filter.type, &filter.flag))
+	{
+		DBG1(DBG_CFG, "invalid certificate type '%s'", str);
+		goto finalize;
+	}
+
+	str = request->get_str(request, NULL, "subject");
+	if (str)
+	{
+		filter.subject = identification_create_from_string(str);
+	}
+
+	enum_certs(this, id, &filter, CERT_TRUSTED_PUBKEY);
+	enum_certs(this, id, &filter, CERT_X509);
+	enum_certs(this, id, &filter, CERT_X509_AC);
+	enum_certs(this, id, &filter, CERT_X509_CRL);
+	enum_certs(this, id, &filter, CERT_X509_OCSP_RESPONSE);
+	DESTROY_IF(filter.subject);
+
+finalize:
 	b = vici_builder_create();
 	return b->finalize(b);
 }
 
-CALLBACK(version, vici_message_t*,
+/**
+ * Add a key/value pair of ALG => plugin
+ */
+static void add_algorithm(vici_builder_t *b, enum_name_t *alg_names,
+						  int alg_type, const char *plugin_name)
+{
+	char alg_name[BUF_LEN];
+
+	sprintf(alg_name, "%N", alg_names, alg_type);
+	b->add_kv(b, alg_name, (char*)plugin_name);
+}
+
+CALLBACK(get_algorithms, vici_message_t*,
 	private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
 {
 	vici_builder_t *b;
+	enumerator_t *enumerator;
+	encryption_algorithm_t encryption;
+	integrity_algorithm_t integrity;
+	hash_algorithm_t hash;
+	pseudo_random_function_t prf;
+	diffie_hellman_group_t group;
+	rng_quality_t quality;
+	const char *plugin_name;
 
 	b = vici_builder_create();
 
+	b->begin_section(b, "encryption");
+	enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
+	while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
+	{
+		add_algorithm(b, encryption_algorithm_names, encryption, plugin_name);
+	}
+	enumerator->destroy(enumerator);
+	b->end_section(b);
+
+	b->begin_section(b, "integrity");
+	enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
+	while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
+	{
+		add_algorithm(b, integrity_algorithm_names, integrity, plugin_name);
+	}
+	enumerator->destroy(enumerator);
+	b->end_section(b);
+
+	b->begin_section(b, "aead");
+	enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
+	while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
+	{
+		add_algorithm(b, encryption_algorithm_names, encryption, plugin_name);
+	}
+	enumerator->destroy(enumerator);
+	b->end_section(b);
+
+	b->begin_section(b, "hasher");
+	enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
+	while (enumerator->enumerate(enumerator, &hash, &plugin_name))
+	{
+		add_algorithm(b, hash_algorithm_names, hash, plugin_name);
+	}
+	enumerator->destroy(enumerator);
+	b->end_section(b);
+
+	b->begin_section(b, "prf");
+	enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
+	while (enumerator->enumerate(enumerator, &prf, &plugin_name))
+	{
+		add_algorithm(b, pseudo_random_function_names, prf, plugin_name);
+	}
+	enumerator->destroy(enumerator);
+	b->end_section(b);
+
+	b->begin_section(b, "dh");
+	enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
+	while (enumerator->enumerate(enumerator, &group, &plugin_name))
+	{
+		add_algorithm(b, diffie_hellman_group_names, group, plugin_name);
+	}
+	enumerator->destroy(enumerator);
+	b->end_section(b);
+
+	b->begin_section(b, "rng");
+	enumerator = lib->crypto->create_rng_enumerator(lib->crypto);
+	while (enumerator->enumerate(enumerator, &quality, &plugin_name))
+	{
+		add_algorithm(b, rng_quality_names, quality, plugin_name);
+	}
+	enumerator->destroy(enumerator);
+	b->end_section(b);
+
+	b->begin_section(b, "nonce-gen");
+	enumerator = lib->crypto->create_nonce_gen_enumerator(lib->crypto);
+	while (enumerator->enumerate(enumerator, &plugin_name))
+	{
+		b->add_kv(b, "NONCE_GEN", (char*)plugin_name);
+	}
+	enumerator->destroy(enumerator);
+	b->end_section(b);
+
+	return b->finalize(b);
+}
+
+CALLBACK(version, vici_message_t*,
+	private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
+{
+	vici_builder_t *b;
+
+	b = vici_builder_create();
 	b->add_kv(b, "daemon", "%s", lib->ns);
 	b->add_kv(b, "version", "%s", VERSION);
 
@@ -915,18 +1175,6 @@ CALLBACK(version, vici_message_t*,
 	return b->finalize(b);
 }
 
-/**
- * Callback function for memusage summary
- */
-CALLBACK(sum_usage, void,
-	vici_builder_t *b, int count, size_t bytes, int whitelisted)
-{
-	b->begin_section(b, "mem");
-	b->add_kv(b, "total", "%zu", bytes);
-	b->add_kv(b, "allocs", "%d", count);
-	b->end_section(b);
-}
-
 CALLBACK(stats, vici_message_t*,
 	private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
 {
@@ -988,12 +1236,7 @@ CALLBACK(stats, vici_message_t*,
 	enumerator->destroy(enumerator);
 	b->end_list(b);
 
-	if (lib->leak_detective)
-	{
-		lib->leak_detective->usage(lib->leak_detective, NULL, sum_usage, b);
-	}
 #ifdef WIN32
-	else
 	{
 		DWORD lasterr = ERROR_INVALID_HANDLE;
 		HANDLE heaps[32];
@@ -1085,6 +1328,7 @@ static void manage_commands(private_vici_query_t *this, bool reg)
 	manage_command(this, "list-policies", list_policies, reg);
 	manage_command(this, "list-conns", list_conns, reg);
 	manage_command(this, "list-certs", list_certs, reg);
+	manage_command(this, "get-algorithms", get_algorithms, reg);
 	manage_command(this, "version", version, reg);
 	manage_command(this, "stats", stats, reg);
 }
diff --git a/src/libcharon/plugins/vici/vici_tests.c b/src/libcharon/plugins/vici/vici_tests.c
index 434aa5e..d1f8097 100644
--- a/src/libcharon/plugins/vici/vici_tests.c
+++ b/src/libcharon/plugins/vici/vici_tests.c
@@ -16,7 +16,6 @@
 #include <test_runner.h>
 
 #include <daemon.h>
-#include <hydra.h>
 
 /* declare test suite constructors */
 #define TEST_SUITE(x) test_suite_t* x();
diff --git a/src/libcharon/plugins/whitelist/Makefile.am b/src/libcharon/plugins/whitelist/Makefile.am
index 1fd01c8..7f6bfff 100644
--- a/src/libcharon/plugins/whitelist/Makefile.am
+++ b/src/libcharon/plugins/whitelist/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
diff --git a/src/libcharon/plugins/whitelist/Makefile.in b/src/libcharon/plugins/whitelist/Makefile.in
index e400d9f..549ef6b 100644
--- a/src/libcharon/plugins/whitelist/Makefile.in
+++ b/src/libcharon/plugins/whitelist/Makefile.in
@@ -423,6 +423,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -438,7 +440,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
diff --git a/src/libcharon/plugins/xauth_eap/Makefile.am b/src/libcharon/plugins/xauth_eap/Makefile.am
index ea75c15..5c7228e 100644
--- a/src/libcharon/plugins/xauth_eap/Makefile.am
+++ b/src/libcharon/plugins/xauth_eap/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/xauth_eap/Makefile.in b/src/libcharon/plugins/xauth_eap/Makefile.in
index a968445..6992df8 100644
--- a/src/libcharon/plugins/xauth_eap/Makefile.in
+++ b/src/libcharon/plugins/xauth_eap/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/xauth_generic/Makefile.am b/src/libcharon/plugins/xauth_generic/Makefile.am
index 1ecd9fd..282bfc4 100644
--- a/src/libcharon/plugins/xauth_generic/Makefile.am
+++ b/src/libcharon/plugins/xauth_generic/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/xauth_generic/Makefile.in b/src/libcharon/plugins/xauth_generic/Makefile.in
index 5170c92..057a734 100644
--- a/src/libcharon/plugins/xauth_generic/Makefile.in
+++ b/src/libcharon/plugins/xauth_generic/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/xauth_noauth/Makefile.am b/src/libcharon/plugins/xauth_noauth/Makefile.am
index 3902471..bb41f21 100644
--- a/src/libcharon/plugins/xauth_noauth/Makefile.am
+++ b/src/libcharon/plugins/xauth_noauth/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/xauth_noauth/Makefile.in b/src/libcharon/plugins/xauth_noauth/Makefile.in
index 087f5b3..6b0104e 100644
--- a/src/libcharon/plugins/xauth_noauth/Makefile.in
+++ b/src/libcharon/plugins/xauth_noauth/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/xauth_pam/Makefile.am b/src/libcharon/plugins/xauth_pam/Makefile.am
index abf83ca..cee8bf8 100644
--- a/src/libcharon/plugins/xauth_pam/Makefile.am
+++ b/src/libcharon/plugins/xauth_pam/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/plugins/xauth_pam/Makefile.in b/src/libcharon/plugins/xauth_pam/Makefile.in
index 29441bc..ae6a4d0 100644
--- a/src/libcharon/plugins/xauth_pam/Makefile.in
+++ b/src/libcharon/plugins/xauth_pam/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -431,7 +433,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
diff --git a/src/libcharon/processing/jobs/adopt_children_job.c b/src/libcharon/processing/jobs/adopt_children_job.c
index b4f135a..c396890 100644
--- a/src/libcharon/processing/jobs/adopt_children_job.c
+++ b/src/libcharon/processing/jobs/adopt_children_job.c
@@ -19,7 +19,6 @@
 #include "adopt_children_job.h"
 
 #include <daemon.h>
-#include <hydra.h>
 #include <collections/array.h>
 #include <processing/jobs/delete_ike_sa_job.h>
 
diff --git a/src/libcharon/processing/jobs/redirect_job.c b/src/libcharon/processing/jobs/redirect_job.c
new file mode 100644
index 0000000..e1af662
--- /dev/null
+++ b/src/libcharon/processing/jobs/redirect_job.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include <daemon.h>
+
+#include "redirect_job.h"
+
+typedef struct private_redirect_job_t private_redirect_job_t;
+
+/**
+ * Private data
+ */
+struct private_redirect_job_t {
+
+	/**
+	 * Public interface
+	 */
+	redirect_job_t public;
+
+	/**
+	 * ID of the IKE_SA to redirect
+	 */
+	ike_sa_id_t *ike_sa_id;
+
+	/**
+	 * Target gateway identity
+	 */
+	identification_t *gateway;
+};
+
+
+METHOD(job_t, destroy, void,
+	private_redirect_job_t *this)
+{
+	this->ike_sa_id->destroy(this->ike_sa_id);
+	this->gateway->destroy(this->gateway);
+	free(this);
+}
+
+METHOD(job_t, execute, job_requeue_t,
+	private_redirect_job_t *this)
+{
+	ike_sa_t *ike_sa;
+
+	ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+											  this->ike_sa_id);
+	if (ike_sa)
+	{
+		if (ike_sa->get_state(ike_sa) == IKE_PASSIVE)
+		{
+			charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+			return JOB_REQUEUE_NONE;
+		}
+		if (ike_sa->redirect(ike_sa, this->gateway) == DESTROY_ME)
+		{
+			charon->ike_sa_manager->checkin_and_destroy(
+											charon->ike_sa_manager, ike_sa);
+		}
+		else
+		{
+			charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+		}
+	}
+	return JOB_REQUEUE_NONE;
+}
+
+METHOD(job_t, get_priority, job_priority_t,
+	private_redirect_job_t *this)
+{
+	return JOB_PRIO_MEDIUM;
+}
+
+/*
+ * Described in header
+ */
+redirect_job_t *redirect_job_create(ike_sa_id_t *ike_sa_id,
+									identification_t *gateway)
+{
+	private_redirect_job_t *this;
+
+	INIT(this,
+		.public = {
+			.job_interface = {
+				.execute = _execute,
+				.get_priority = _get_priority,
+				.destroy = _destroy,
+			},
+		},
+		.ike_sa_id = ike_sa_id->clone(ike_sa_id),
+		.gateway = gateway->clone(gateway),
+	);
+
+	return &(this->public);
+}
diff --git a/src/libcharon/processing/jobs/redirect_job.h b/src/libcharon/processing/jobs/redirect_job.h
new file mode 100644
index 0000000..fe4b34e
--- /dev/null
+++ b/src/libcharon/processing/jobs/redirect_job.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+/**
+ * @defgroup redirect_job redirect_job
+ * @{ @ingroup cjobs
+ */
+
+#ifndef REDIRECT_JOB_H_
+#define REDIRECT_JOB_H_
+
+typedef struct redirect_job_t redirect_job_t;
+
+#include <library.h>
+#include <sa/ike_sa_id.h>
+#include <processing/jobs/job.h>
+
+/**
+ * Job used to redirect an IKE_SA.
+ */
+struct redirect_job_t {
+
+	/**
+	 * The job_t interface.
+	 */
+	job_t job_interface;
+};
+
+/**
+ * Creates a job to redirect an IKE_SA.
+ *
+ * @param ike_sa_id			id of the IKE_SA to redirect (cloned)
+ * @param gateway			gateway identity (IP or FQDN) of target (cloned)
+ * @return					created redirect_job_t object
+ */
+redirect_job_t *redirect_job_create(ike_sa_id_t *ike_sa_id,
+									identification_t *gateway);
+
+#endif /** REDIRECT_JOB_H_ @}*/
diff --git a/src/libcharon/processing/jobs/send_keepalive_job.c b/src/libcharon/processing/jobs/send_keepalive_job.c
index 3e34776..e06eae3 100644
--- a/src/libcharon/processing/jobs/send_keepalive_job.c
+++ b/src/libcharon/processing/jobs/send_keepalive_job.c
@@ -54,7 +54,7 @@ METHOD(job_t, execute, job_requeue_t,
 											  this->ike_sa_id);
 	if (ike_sa)
 	{
-		ike_sa->send_keepalive(ike_sa);
+		ike_sa->send_keepalive(ike_sa, TRUE);
 		charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
 	}
 	return JOB_REQUEUE_NONE;
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index b0f163c..56b7cb5 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -23,7 +23,6 @@
 #include <string.h>
 #include <time.h>
 
-#include <hydra.h>
 #include <daemon.h>
 #include <collections/array.h>
 
@@ -469,10 +468,10 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
 	{
 		if (this->my_spi)
 		{
-			status = hydra->kernel_interface->query_sa(hydra->kernel_interface,
-							this->other_addr, this->my_addr, this->my_spi,
-							proto_ike2ip(this->protocol), this->mark_in,
-							&bytes, &packets, &time);
+			status = charon->kernel->query_sa(charon->kernel, this->other_addr,
+									this->my_addr, this->my_spi,
+									proto_ike2ip(this->protocol), this->mark_in,
+									&bytes, &packets, &time);
 			if (status == SUCCESS)
 			{
 				if (bytes > this->my_usebytes)
@@ -493,10 +492,10 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
 	{
 		if (this->other_spi)
 		{
-			status = hydra->kernel_interface->query_sa(hydra->kernel_interface,
-							this->my_addr, this->other_addr, this->other_spi,
-							proto_ike2ip(this->protocol), this->mark_out,
-							&bytes, &packets, &time);
+			status = charon->kernel->query_sa(charon->kernel, this->my_addr,
+								this->other_addr, this->other_spi,
+								proto_ike2ip(this->protocol), this->mark_out,
+								&bytes, &packets, &time);
 			if (status == SUCCESS)
 			{
 				if (bytes > this->other_usebytes)
@@ -532,15 +531,15 @@ static bool update_usetime(private_child_sa_t *this, bool inbound)
 
 		if (inbound)
 		{
-			if (hydra->kernel_interface->query_policy(hydra->kernel_interface,
-						other_ts, my_ts, POLICY_IN, this->mark_in, &in) == SUCCESS)
+			if (charon->kernel->query_policy(charon->kernel, other_ts,
+							my_ts, POLICY_IN, this->mark_in, &in) == SUCCESS)
 			{
 				last_use = max(last_use, in);
 			}
 			if (this->mode != MODE_TRANSPORT)
 			{
-				if (hydra->kernel_interface->query_policy(hydra->kernel_interface,
-						other_ts, my_ts, POLICY_FWD, this->mark_in, &fwd) == SUCCESS)
+				if (charon->kernel->query_policy(charon->kernel, other_ts,
+							my_ts, POLICY_FWD, this->mark_in, &fwd) == SUCCESS)
 				{
 					last_use = max(last_use, fwd);
 				}
@@ -548,8 +547,8 @@ static bool update_usetime(private_child_sa_t *this, bool inbound)
 		}
 		else
 		{
-			if (hydra->kernel_interface->query_policy(hydra->kernel_interface,
-						my_ts, other_ts, POLICY_OUT, this->mark_out, &out) == SUCCESS)
+			if (charon->kernel->query_policy(charon->kernel, my_ts,
+							other_ts, POLICY_OUT, this->mark_out, &out) == SUCCESS)
 			{
 				last_use = max(last_use, out);
 			}
@@ -629,10 +628,8 @@ METHOD(child_sa_t, get_installtime, time_t,
 METHOD(child_sa_t, alloc_spi, u_int32_t,
 	   private_child_sa_t *this, protocol_id_t protocol)
 {
-	if (hydra->kernel_interface->get_spi(hydra->kernel_interface,
-										 this->other_addr, this->my_addr,
-										 proto_ike2ip(protocol),
-										 &this->my_spi) == SUCCESS)
+	if (charon->kernel->get_spi(charon->kernel, this->other_addr, this->my_addr,
+							proto_ike2ip(protocol), &this->my_spi) == SUCCESS)
 	{
 		/* if we allocate a SPI, but then are unable to establish the SA, we
 		 * need to know the protocol family to delete the partial SA */
@@ -645,9 +642,8 @@ METHOD(child_sa_t, alloc_spi, u_int32_t,
 METHOD(child_sa_t, alloc_cpi, u_int16_t,
 	   private_child_sa_t *this)
 {
-	if (hydra->kernel_interface->get_cpi(hydra->kernel_interface,
-										 this->other_addr, this->my_addr,
-										 &this->my_cpi) == SUCCESS)
+	if (charon->kernel->get_cpi(charon->kernel, this->other_addr, this->my_addr,
+								&this->my_cpi) == SUCCESS)
 	{
 		return this->my_cpi;
 	}
@@ -711,9 +707,8 @@ METHOD(child_sa_t, install, status_t,
 
 	if (!this->reqid_allocated && !this->static_reqid)
 	{
-		status = hydra->kernel_interface->alloc_reqid(hydra->kernel_interface,
-							my_ts, other_ts, this->mark_in, this->mark_out,
-							&this->reqid);
+		status = charon->kernel->alloc_reqid(charon->kernel, my_ts, other_ts,
+								this->mark_in, this->mark_out, &this->reqid);
 		if (status != SUCCESS)
 		{
 			return status;
@@ -757,7 +752,7 @@ METHOD(child_sa_t, install, status_t,
 		dst_ts = other_ts;
 	}
 
-	status = hydra->kernel_interface->add_sa(hydra->kernel_interface,
+	status = charon->kernel->add_sa(charon->kernel,
 				src, dst, spi, proto_ike2ip(this->protocol), this->reqid,
 				inbound ? this->mark_in : this->mark_out, tfc,
 				lifetime, enc_alg, encr, int_alg, integ, this->mode,
@@ -776,7 +771,7 @@ static bool require_policy_update()
 {
 	kernel_feature_t f;
 
-	f = hydra->kernel_interface->get_features(hydra->kernel_interface);
+	f = charon->kernel->get_features(charon->kernel);
 	return !(f & KERNEL_NO_POLICY_UPDATES);
 }
 
@@ -833,18 +828,18 @@ static status_t install_policies_internal(private_child_sa_t *this,
 	ipsec_sa_cfg_t *other_sa, policy_type_t type, policy_priority_t priority)
 {
 	status_t status = SUCCESS;
-	status |= hydra->kernel_interface->add_policy(hydra->kernel_interface,
+	status |= charon->kernel->add_policy(charon->kernel,
 							my_addr, other_addr, my_ts, other_ts,
 							POLICY_OUT, type, other_sa,
 							this->mark_out, priority);
 
-	status |= hydra->kernel_interface->add_policy(hydra->kernel_interface,
+	status |= charon->kernel->add_policy(charon->kernel,
 							other_addr, my_addr, other_ts, my_ts,
 							POLICY_IN, type, my_sa,
 							this->mark_in, priority);
 	if (this->mode != MODE_TRANSPORT)
 	{
-		status |= hydra->kernel_interface->add_policy(hydra->kernel_interface,
+		status |= charon->kernel->add_policy(charon->kernel,
 							other_addr, my_addr, other_ts, my_ts,
 							POLICY_FWD, type, my_sa,
 							this->mark_in, priority);
@@ -861,15 +856,15 @@ static void del_policies_internal(private_child_sa_t *this,
 	ipsec_sa_cfg_t *other_sa, policy_type_t type, policy_priority_t priority)
 {
 
-	hydra->kernel_interface->del_policy(hydra->kernel_interface,
+	charon->kernel->del_policy(charon->kernel,
 						my_addr, other_addr, my_ts, other_ts, POLICY_OUT, type,
 						other_sa, this->mark_out, priority);
-	hydra->kernel_interface->del_policy(hydra->kernel_interface,
+	charon->kernel->del_policy(charon->kernel,
 						other_addr, my_addr, other_ts, my_ts, POLICY_IN,
 						type, my_sa, this->mark_in, priority);
 	if (this->mode != MODE_TRANSPORT)
 	{
-		hydra->kernel_interface->del_policy(hydra->kernel_interface,
+		charon->kernel->del_policy(charon->kernel,
 						other_addr, my_addr, other_ts, my_ts, POLICY_FWD,
 						type, my_sa, this->mark_in, priority);
 	}
@@ -886,8 +881,8 @@ METHOD(child_sa_t, add_policies, status_t,
 	if (!this->reqid_allocated && !this->static_reqid)
 	{
 		/* trap policy, get or confirm reqid */
-		status = hydra->kernel_interface->alloc_reqid(
-							hydra->kernel_interface, my_ts_list, other_ts_list,
+		status = charon->kernel->alloc_reqid(
+							charon->kernel, my_ts_list, other_ts_list,
 							this->mark_in, this->mark_out, &this->reqid);
 		if (status != SUCCESS)
 		{
@@ -967,11 +962,10 @@ static void reinstall_vip(host_t *vip, host_t *me)
 {
 	char *iface;
 
-	if (hydra->kernel_interface->get_interface(hydra->kernel_interface,
-											   me, &iface))
+	if (charon->kernel->get_interface(charon->kernel, me, &iface))
 	{
-		hydra->kernel_interface->del_ip(hydra->kernel_interface, vip, -1, TRUE);
-		hydra->kernel_interface->add_ip(hydra->kernel_interface, vip, -1, iface);
+		charon->kernel->del_ip(charon->kernel, vip, -1, TRUE);
+		charon->kernel->add_ip(charon->kernel, vip, -1, iface);
 		free(iface);
 	}
 }
@@ -1000,7 +994,7 @@ METHOD(child_sa_t, update, status_t,
 		/* update our (initiator) SA */
 		if (this->my_spi)
 		{
-			if (hydra->kernel_interface->update_sa(hydra->kernel_interface,
+			if (charon->kernel->update_sa(charon->kernel,
 							this->my_spi, proto_ike2ip(this->protocol),
 							this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
 							this->other_addr, this->my_addr, other, me,
@@ -1014,7 +1008,7 @@ METHOD(child_sa_t, update, status_t,
 		/* update his (responder) SA */
 		if (this->other_spi)
 		{
-			if (hydra->kernel_interface->update_sa(hydra->kernel_interface,
+			if (charon->kernel->update_sa(charon->kernel,
 							this->other_spi, proto_ike2ip(this->protocol),
 							this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
 							this->my_addr, this->other_addr, me, other,
@@ -1143,14 +1137,14 @@ METHOD(child_sa_t, destroy, void,
 	/* delete SAs in the kernel, if they are set up */
 	if (this->my_spi)
 	{
-		hydra->kernel_interface->del_sa(hydra->kernel_interface,
+		charon->kernel->del_sa(charon->kernel,
 					this->other_addr, this->my_addr, this->my_spi,
 					proto_ike2ip(this->protocol), this->my_cpi,
 					this->mark_in);
 	}
 	if (this->other_spi)
 	{
-		hydra->kernel_interface->del_sa(hydra->kernel_interface,
+		charon->kernel->del_sa(charon->kernel,
 					this->my_addr, this->other_addr, this->other_spi,
 					proto_ike2ip(this->protocol), this->other_cpi,
 					this->mark_out);
@@ -1158,7 +1152,7 @@ METHOD(child_sa_t, destroy, void,
 
 	if (this->reqid_allocated)
 	{
-		if (hydra->kernel_interface->release_reqid(hydra->kernel_interface,
+		if (charon->kernel->release_reqid(charon->kernel,
 						this->reqid, this->mark_in, this->mark_out) != SUCCESS)
 		{
 			DBG1(DBG_CHD, "releasing reqid %u failed", this->reqid);
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index dcf9d5f..bcbff32 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -46,7 +46,6 @@
 #include "ike_sa.h"
 
 #include <library.h>
-#include <hydra.h>
 #include <daemon.h>
 #include <collections/array.h>
 #include <utils/lexparser.h>
@@ -57,6 +56,9 @@
 #include <processing/jobs/rekey_ike_sa_job.h>
 #include <processing/jobs/retry_initiate_job.h>
 #include <sa/ikev2/tasks/ike_auth_lifetime.h>
+#include <sa/ikev2/tasks/ike_reauth_complete.h>
+#include <sa/ikev2/tasks/ike_redirect.h>
+#include <credentials/sets/auth_cfg_wrapper.h>
 
 #ifdef ME
 #include <sa/ikev2/tasks/ike_me.h>
@@ -239,6 +241,11 @@ struct private_ike_sa_t {
 	u_int32_t keepalive_interval;
 
 	/**
+	 * The schedueld keep alive job, if any
+	 */
+	send_keepalive_job_t *keepalive_job;
+
+	/**
 	 * interval for retries during initiation (e.g. if DNS resolution failed),
 	 * 0 to disable (default)
 	 */
@@ -278,6 +285,21 @@ struct private_ike_sa_t {
 	 * Maximum length of a single fragment, 0 for address-specific defaults
 	 */
 	size_t fragment_size;
+
+	/**
+	 * Whether to follow IKEv2 redirects
+	 */
+	bool follow_redirects;
+
+	/**
+	 * Original gateway address from which we got redirected
+	 */
+	host_t *redirected_from;
+
+	/**
+	 * Timestamps of redirect attempts to handle loops
+	 */
+	array_t *redirected_at;
 };
 
 /**
@@ -382,6 +404,12 @@ METHOD(ike_sa_t, set_other_host, void,
 	this->other_host = other;
 }
 
+METHOD(ike_sa_t, get_redirected_from, host_t*,
+	private_ike_sa_t *this)
+{
+	return this->redirected_from;
+}
+
 METHOD(ike_sa_t, get_peer_cfg, peer_cfg_t*,
 	private_ike_sa_t *this)
 {
@@ -455,6 +483,113 @@ static void flush_auth_cfgs(private_ike_sa_t *this)
 	}
 }
 
+METHOD(ike_sa_t, verify_peer_certificate, bool,
+	private_ike_sa_t *this)
+{
+	enumerator_t *e1, *e2, *certs;
+	auth_cfg_t *cfg, *cfg_done;
+	certificate_t *peer, *cert;
+	public_key_t *key;
+	auth_cfg_t *auth;
+	auth_cfg_wrapper_t *wrapper;
+	time_t not_before, not_after;
+	bool valid = TRUE, found;
+
+	if (this->state != IKE_ESTABLISHED)
+	{
+		DBG1(DBG_IKE, "unable to verify peer certificate in state %N",
+			 ike_sa_state_names, this->state);
+		return FALSE;
+	}
+
+	if (!this->flush_auth_cfg &&
+		lib->settings->get_bool(lib->settings,
+								"%s.flush_auth_cfg", FALSE, lib->ns))
+	{	/* we can do this check only once if auth configs are flushed */
+		DBG1(DBG_IKE, "unable to verify peer certificate as authentication "
+			 "information has been flushed");
+		return FALSE;
+	}
+	this->public.set_condition(&this->public, COND_ONLINE_VALIDATION_SUSPENDED,
+							   FALSE);
+
+	e1 = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, FALSE);
+	e2 = array_create_enumerator(this->other_auths);
+	while (e1->enumerate(e1, &cfg))
+	{
+		if (!e2->enumerate(e2, &cfg_done))
+		{	/* this should not happen as the authentication should never have
+			 * succeeded */
+			valid = FALSE;
+			break;
+		}
+		if ((uintptr_t)cfg_done->get(cfg_done,
+									 AUTH_RULE_AUTH_CLASS) != AUTH_CLASS_PUBKEY)
+		{
+			continue;
+		}
+		peer = cfg_done->get(cfg_done, AUTH_RULE_SUBJECT_CERT);
+		if (!peer)
+		{
+			DBG1(DBG_IKE, "no subject certificate found, skipping certificate "
+				 "verification");
+			continue;
+		}
+		if (!peer->get_validity(peer, NULL, &not_before, &not_after))
+		{
+			DBG1(DBG_IKE, "peer certificate invalid (valid from %T to %T)",
+				 &not_before, FALSE, &not_after, FALSE);
+			valid = FALSE;
+			break;
+		}
+		key = peer->get_public_key(peer);
+		if (!key)
+		{
+			DBG1(DBG_IKE, "unable to retrieve public key, skipping certificate "
+				 "verification");
+			continue;
+		}
+		DBG1(DBG_IKE, "verifying peer certificate");
+		/* serve received certificates */
+		wrapper = auth_cfg_wrapper_create(cfg_done);
+		lib->credmgr->add_local_set(lib->credmgr, &wrapper->set, FALSE);
+		certs = lib->credmgr->create_trusted_enumerator(lib->credmgr,
+							key->get_type(key), peer->get_subject(peer), TRUE);
+		key->destroy(key);
+
+		found = FALSE;
+		while (certs->enumerate(certs, &cert, &auth))
+		{
+			if (peer->equals(peer, cert))
+			{
+				cfg_done->add(cfg_done, AUTH_RULE_CERT_VALIDATION_SUSPENDED,
+							  FALSE);
+				cfg_done->merge(cfg_done, auth, FALSE);
+				valid = cfg_done->complies(cfg_done, cfg, TRUE);
+				found = TRUE;
+				break;
+			}
+		}
+		certs->destroy(certs);
+		lib->credmgr->remove_local_set(lib->credmgr, &wrapper->set);
+		wrapper->destroy(wrapper);
+		if (!found || !valid)
+		{
+			valid = FALSE;
+			break;
+		}
+	}
+	e1->destroy(e1);
+	e2->destroy(e2);
+
+	if (this->flush_auth_cfg)
+	{
+		this->flush_auth_cfg = FALSE;
+		flush_auth_cfgs(this);
+	}
+	return valid;
+}
+
 METHOD(ike_sa_t, get_proposal, proposal_t*,
 	private_ike_sa_t *this)
 {
@@ -482,14 +617,20 @@ METHOD(ike_sa_t, set_message_id, void,
 }
 
 METHOD(ike_sa_t, send_keepalive, void,
-	private_ike_sa_t *this)
+	private_ike_sa_t *this, bool scheduled)
 {
-	send_keepalive_job_t *job;
 	time_t last_out, now, diff;
 
-	if (!(this->conditions & COND_NAT_HERE) || this->keepalive_interval == 0 ||
-		this->state == IKE_PASSIVE)
-	{	/* disable keep alives if we are not NATed anymore, or we are passive */
+	if (scheduled)
+	{
+		this->keepalive_job = NULL;
+	}
+	if (!this->keepalive_interval || this->state == IKE_PASSIVE)
+	{	/* keepalives disabled either by configuration or for passive IKE_SAs */
+		return;
+	}
+	if (!(this->conditions & COND_NAT_HERE) || (this->conditions & COND_STALE))
+	{	/* disable keepalives if we are not NATed anymore, or the SA is stale */
 		return;
 	}
 
@@ -514,9 +655,12 @@ METHOD(ike_sa_t, send_keepalive, void,
 		charon->sender->send_no_marker(charon->sender, packet);
 		diff = 0;
 	}
-	job = send_keepalive_job_create(this->ike_sa_id);
-	lib->scheduler->schedule_job(lib->scheduler, (job_t*)job,
-								 this->keepalive_interval - diff);
+	if (!this->keepalive_job)
+	{
+		this->keepalive_job = send_keepalive_job_create(this->ike_sa_id);
+		lib->scheduler->schedule_job(lib->scheduler, (job_t*)this->keepalive_job,
+									 this->keepalive_interval - diff);
+	}
 }
 
 METHOD(ike_sa_t, get_ike_cfg, ike_cfg_t*,
@@ -563,7 +707,7 @@ METHOD(ike_sa_t, set_condition, void,
 				case COND_NAT_HERE:
 					DBG1(DBG_IKE, "local host is behind NAT, sending keep alives");
 					this->conditions |= COND_NAT_ANY;
-					send_keepalive(this);
+					send_keepalive(this, FALSE);
 					break;
 				case COND_NAT_THERE:
 					DBG1(DBG_IKE, "remote host is behind NAT");
@@ -590,6 +734,9 @@ METHOD(ike_sa_t, set_condition, void,
 								  has_condition(this, COND_NAT_THERE) ||
 								  has_condition(this, COND_NAT_FAKE));
 					break;
+				case COND_STALE:
+					send_keepalive(this, FALSE);
+					break;
 				default:
 					break;
 			}
@@ -727,6 +874,8 @@ METHOD(ike_sa_t, set_state, void,
 				{
 					keepalives = TRUE;
 				}
+				DESTROY_IF(this->redirected_from);
+				this->redirected_from = NULL;
 			}
 			break;
 		}
@@ -749,7 +898,7 @@ METHOD(ike_sa_t, set_state, void,
 	}
 	if (keepalives)
 	{
-		send_keepalive(this);
+		send_keepalive(this, FALSE);
 	}
 }
 
@@ -786,12 +935,12 @@ METHOD(ike_sa_t, add_virtual_ip, void,
 	{
 		char *iface;
 
-		if (hydra->kernel_interface->get_interface(hydra->kernel_interface,
-												   this->my_host, &iface))
+		if (charon->kernel->get_interface(charon->kernel, this->my_host,
+										  &iface))
 		{
 			DBG1(DBG_IKE, "installing new virtual IP %H", ip);
-			if (hydra->kernel_interface->add_ip(hydra->kernel_interface,
-												ip, -1, iface) == SUCCESS)
+			if (charon->kernel->add_ip(charon->kernel, ip, -1,
+									   iface) == SUCCESS)
 			{
 				array_insert_create(&this->my_vips, ARRAY_TAIL, ip->clone(ip));
 			}
@@ -828,8 +977,7 @@ METHOD(ike_sa_t, clear_virtual_ips, void,
 	{
 		if (local)
 		{
-			hydra->kernel_interface->del_ip(hydra->kernel_interface,
-											vip, -1, TRUE);
+			charon->kernel->del_ip(charon->kernel, vip, -1, TRUE);
 		}
 		vip->destroy(vip);
 	}
@@ -1265,8 +1413,8 @@ static void resolve_hosts(private_ike_sa_t *this)
 			!this->other_host->is_anyaddr(this->other_host))
 		{
 			host->destroy(host);
-			host = hydra->kernel_interface->get_source_addr(
-							hydra->kernel_interface, this->other_host, NULL);
+			host = charon->kernel->get_source_addr(charon->kernel,
+												   this->other_host, NULL);
 			if (host)
 			{
 				host->set_port(host, this->ike_cfg->get_my_port(this->ike_cfg));
@@ -1401,9 +1549,14 @@ METHOD(ike_sa_t, process_message, status_t,
 	status = this->task_manager->process_message(this->task_manager, message);
 	if (this->flush_auth_cfg && this->state == IKE_ESTABLISHED)
 	{
-		/* authentication completed */
-		this->flush_auth_cfg = FALSE;
-		flush_auth_cfgs(this);
+		/* authentication completed but if the online validation is suspended we
+		 * need the auth cfgs until we did the delayed verification, we flush
+		 * them afterwards */
+		if (!has_condition(this, COND_ONLINE_VALIDATION_SUSPENDED))
+		{
+			this->flush_auth_cfg = FALSE;
+			flush_auth_cfgs(this);
+		}
 	}
 	return status;
 }
@@ -1735,6 +1888,86 @@ static bool is_child_queued(private_ike_sa_t *this, task_queue_t queue)
 	return found;
 }
 
+/**
+ * Reestablish CHILD_SAs and migrate queued tasks.
+ *
+ * If force is true all SAs are restarted, otherwise their close/dpd_action
+ * is followed.
+ */
+static status_t reestablish_children(private_ike_sa_t *this, ike_sa_t *new,
+									 bool force)
+{
+	enumerator_t *enumerator;
+	child_sa_t *child_sa;
+	child_cfg_t *child_cfg;
+	action_t action;
+	status_t status = FAILED;
+
+	/* handle existing CHILD_SAs */
+	enumerator = create_child_sa_enumerator(this);
+	while (enumerator->enumerate(enumerator, (void**)&child_sa))
+	{
+		if (force)
+		{
+			switch (child_sa->get_state(child_sa))
+			{
+				case CHILD_ROUTED:
+				{	/* move routed child directly */
+					remove_child_sa(this, enumerator);
+					new->add_child_sa(new, child_sa);
+					action = ACTION_NONE;
+					break;
+				}
+				default:
+				{	/* initiate/queue all other CHILD_SAs */
+					action = ACTION_RESTART;
+					break;
+				}
+			}
+		}
+		else
+		{	/* only restart CHILD_SAs that are configured accordingly */
+			if (this->state == IKE_DELETING)
+			{
+				action = child_sa->get_close_action(child_sa);
+			}
+			else
+			{
+				action = child_sa->get_dpd_action(child_sa);
+			}
+		}
+		switch (action)
+		{
+			case ACTION_RESTART:
+				child_cfg = child_sa->get_config(child_sa);
+				DBG1(DBG_IKE, "restarting CHILD_SA %s",
+					 child_cfg->get_name(child_cfg));
+				child_cfg->get_ref(child_cfg);
+				status = new->initiate(new, child_cfg,
+								child_sa->get_reqid(child_sa), NULL, NULL);
+				break;
+			default:
+				continue;
+		}
+		if (status == DESTROY_ME)
+		{
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+	/* adopt any active or queued CHILD-creating tasks */
+	if (status != DESTROY_ME)
+	{
+		task_manager_t *other_tasks = ((private_ike_sa_t*)new)->task_manager;
+		other_tasks->adopt_child_tasks(other_tasks, this->task_manager);
+		if (new->get_state(new) == IKE_CREATED)
+		{
+			status = new->initiate(new, NULL, 0, NULL, NULL);
+		}
+	}
+	return status;
+}
+
 METHOD(ike_sa_t, reestablish, status_t,
 	private_ike_sa_t *this)
 {
@@ -1743,7 +1976,6 @@ METHOD(ike_sa_t, reestablish, status_t,
 	action_t action;
 	enumerator_t *enumerator;
 	child_sa_t *child_sa;
-	child_cfg_t *child_cfg;
 	bool restart = FALSE;
 	status_t status = FAILED;
 
@@ -1836,8 +2068,11 @@ METHOD(ike_sa_t, reestablish, status_t,
 	host = this->my_host;
 	new->set_my_host(new, host->clone(host));
 	charon->bus->ike_reestablish_pre(charon->bus, &this->public, new);
-	/* resolve hosts but use the old addresses above as fallback */
-	resolve_hosts((private_ike_sa_t*)new);
+	if (!has_condition(this, COND_REAUTHENTICATING))
+	{	/* reauthenticate to the same addresses, but resolve hosts if
+		 * reestablishing (old addresses serve as fallback) */
+		resolve_hosts((private_ike_sa_t*)new);
+	}
 	/* if we already have a virtual IP, we reuse it */
 	enumerator = array_create_enumerator(this->my_vips);
 	while (enumerator->enumerate(enumerator, &host))
@@ -1854,68 +2089,8 @@ METHOD(ike_sa_t, reestablish, status_t,
 	else
 #endif /* ME */
 	{
-		/* handle existing CHILD_SAs */
-		enumerator = create_child_sa_enumerator(this);
-		while (enumerator->enumerate(enumerator, (void**)&child_sa))
-		{
-			if (has_condition(this, COND_REAUTHENTICATING))
-			{
-				switch (child_sa->get_state(child_sa))
-				{
-					case CHILD_ROUTED:
-					{	/* move routed child directly */
-						remove_child_sa(this, enumerator);
-						new->add_child_sa(new, child_sa);
-						action = ACTION_NONE;
-						break;
-					}
-					default:
-					{	/* initiate/queue all other CHILD_SAs */
-						action = ACTION_RESTART;
-						break;
-					}
-				}
-			}
-			else
-			{	/* only restart CHILD_SAs that are configured accordingly */
-				if (this->state == IKE_DELETING)
-				{
-					action = child_sa->get_close_action(child_sa);
-				}
-				else
-				{
-					action = child_sa->get_dpd_action(child_sa);
-				}
-			}
-			switch (action)
-			{
-				case ACTION_RESTART:
-					child_cfg = child_sa->get_config(child_sa);
-					DBG1(DBG_IKE, "restarting CHILD_SA %s",
-						 child_cfg->get_name(child_cfg));
-					child_cfg->get_ref(child_cfg);
-					status = new->initiate(new, child_cfg,
-									child_sa->get_reqid(child_sa), NULL, NULL);
-					break;
-				default:
-					continue;
-			}
-			if (status == DESTROY_ME)
-			{
-				break;
-			}
-		}
-		enumerator->destroy(enumerator);
-		/* adopt any active or queued CHILD-creating tasks */
-		if (status != DESTROY_ME)
-		{
-			task_manager_t *other_tasks = ((private_ike_sa_t*)new)->task_manager;
-			other_tasks->adopt_child_tasks(other_tasks, this->task_manager);
-			if (new->get_state(new) == IKE_CREATED)
-			{
-				status = new->initiate(new, NULL, 0, NULL, NULL);
-			}
-		}
+		status = reestablish_children(this, new,
+									has_condition(this, COND_REAUTHENTICATING));
 	}
 
 	if (status == DESTROY_ME)
@@ -1936,6 +2111,195 @@ METHOD(ike_sa_t, reestablish, status_t,
 	return status;
 }
 
+/**
+ * Resolve the given gateway ID
+ */
+static host_t *resolve_gateway_id(identification_t *gateway)
+{
+	char gw[BUF_LEN];
+	host_t *addr;
+
+	snprintf(gw, sizeof(gw), "%Y", gateway);
+	gw[sizeof(gw)-1] = '\0';
+	addr = host_create_from_dns(gw, AF_UNSPEC, IKEV2_UDP_PORT);
+	if (!addr)
+	{
+		DBG1(DBG_IKE, "unable to resolve gateway ID '%Y', redirect failed",
+			 gateway);
+	}
+	return addr;
+}
+
+/**
+ * Redirect the current SA to the given target host
+ */
+static bool redirect_established(private_ike_sa_t *this, identification_t *to)
+{
+	private_ike_sa_t *new_priv;
+	ike_sa_t *new;
+	host_t *other;
+	time_t redirect;
+
+	new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
+											   this->version, TRUE);
+	if (!new)
+	{
+		return FALSE;
+	}
+	new_priv = (private_ike_sa_t*)new;
+	new->set_peer_cfg(new, this->peer_cfg);
+	new_priv->redirected_from = this->other_host->clone(this->other_host);
+	charon->bus->ike_reestablish_pre(charon->bus, &this->public, new);
+	other = resolve_gateway_id(to);
+	if (other)
+	{
+		set_my_host(new_priv, this->my_host->clone(this->my_host));
+		/* this allows us to force the remote address while we still properly
+		 * resolve the local address */
+		new_priv->remote_host = other;
+		resolve_hosts(new_priv);
+		new_priv->redirected_at = array_create(sizeof(time_t), MAX_REDIRECTS);
+		while (array_remove(this->redirected_at, ARRAY_HEAD, &redirect))
+		{
+			array_insert(new_priv->redirected_at, ARRAY_TAIL, &redirect);
+		}
+		if (reestablish_children(this, new, TRUE) != DESTROY_ME)
+		{
+#ifdef USE_IKEV2
+			new->queue_task(new, (task_t*)ike_reauth_complete_create(new,
+															 this->ike_sa_id));
+#endif
+			charon->bus->ike_reestablish_post(charon->bus, &this->public, new,
+											  TRUE);
+			charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
+			charon->bus->set_sa(charon->bus, &this->public);
+			return TRUE;
+		}
+	}
+	charon->bus->ike_reestablish_post(charon->bus, &this->public, new,
+									  FALSE);
+	charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, new);
+	charon->bus->set_sa(charon->bus, &this->public);
+	return FALSE;
+}
+
+/**
+ * Redirect the current connecting SA to the given target host
+ */
+static bool redirect_connecting(private_ike_sa_t *this, identification_t *to)
+{
+	host_t *other;
+
+	other = resolve_gateway_id(to);
+	if (!other)
+	{
+		return FALSE;
+	}
+	reset(this);
+	DESTROY_IF(this->redirected_from);
+	this->redirected_from = this->other_host->clone(this->other_host);
+	DESTROY_IF(this->remote_host);
+	/* this allows us to force the remote address while we still properly
+	 * resolve the local address */
+	this->remote_host = other;
+	resolve_hosts(this);
+	return TRUE;
+}
+
+/**
+ * Check if the current redirect exceeds the limits for redirects
+ */
+static bool redirect_count_exceeded(private_ike_sa_t *this)
+{
+	time_t now, redirect;
+
+	now = time_monotonic(NULL);
+	/* remove entries outside the defined period */
+	while (array_get(this->redirected_at, ARRAY_HEAD, &redirect) &&
+		   now - redirect >= REDIRECT_LOOP_DETECT_PERIOD)
+	{
+		array_remove(this->redirected_at, ARRAY_HEAD, NULL);
+	}
+	if (array_count(this->redirected_at) < MAX_REDIRECTS)
+	{
+		if (!this->redirected_at)
+		{
+			this->redirected_at = array_create(sizeof(time_t), MAX_REDIRECTS);
+		}
+		array_insert(this->redirected_at, ARRAY_TAIL, &now);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+METHOD(ike_sa_t, handle_redirect, bool,
+	private_ike_sa_t *this, identification_t *gateway)
+{
+	DBG1(DBG_IKE, "redirected to %Y", gateway);
+	if (!this->follow_redirects)
+	{
+		DBG1(DBG_IKE, "server sent REDIRECT even though we disabled it");
+		return FALSE;
+	}
+	if (redirect_count_exceeded(this))
+	{
+		DBG1(DBG_IKE, "only %d redirects are allowed within %d seconds",
+			 MAX_REDIRECTS, REDIRECT_LOOP_DETECT_PERIOD);
+		return FALSE;
+	}
+
+	switch (this->state)
+	{
+		case IKE_CONNECTING:
+			return redirect_connecting(this, gateway);
+		case IKE_ESTABLISHED:
+			return redirect_established(this, gateway);
+		default:
+			DBG1(DBG_IKE, "unable to handle redirect for IKE_SA in state %N",
+				 ike_sa_state_names, this->state);
+			return FALSE;
+	}
+}
+
+METHOD(ike_sa_t, redirect, status_t,
+	private_ike_sa_t *this, identification_t *gateway)
+{
+	switch (this->state)
+	{
+		case IKE_CONNECTING:
+		case IKE_ESTABLISHED:
+		case IKE_REKEYING:
+			if (has_condition(this, COND_REDIRECTED))
+			{	/* IKE_SA already got redirected */
+				return SUCCESS;
+			}
+			if (has_condition(this, COND_ORIGINAL_INITIATOR))
+			{
+				DBG1(DBG_IKE, "unable to redirect IKE_SA as initiator");
+				return FAILED;
+			}
+			if (this->version == IKEV1)
+			{
+				DBG1(DBG_IKE, "unable to redirect IKEv1 SA");
+				return FAILED;
+			}
+			if (!supports_extension(this, EXT_IKE_REDIRECTION))
+			{
+				DBG1(DBG_IKE, "client does not support IKE redirection");
+				return FAILED;
+			}
+#ifdef USE_IKEV2
+			this->task_manager->queue_task(this->task_manager,
+						(task_t*)ike_redirect_create(&this->public, gateway));
+#endif
+			return this->task_manager->initiate(this->task_manager);
+		default:
+			DBG1(DBG_IKE, "unable to redirect IKE_SA in state %N",
+				 ike_sa_state_names, this->state);
+			return INVALID_STATE;
+	}
+}
+
 METHOD(ike_sa_t, retransmit, status_t,
 	private_ike_sa_t *this, u_int32_t message_id)
 {
@@ -2067,8 +2431,8 @@ static bool is_current_path_valid(private_ike_sa_t *this)
 {
 	bool valid = FALSE;
 	host_t *src;
-	src = hydra->kernel_interface->get_source_addr(hydra->kernel_interface,
-											this->other_host, this->my_host);
+	src = charon->kernel->get_source_addr(charon->kernel, this->other_host,
+										  this->my_host);
 	if (src)
 	{
 		if (src->ip_equals(src, this->my_host))
@@ -2112,8 +2476,7 @@ static bool is_any_path_valid(private_ike_sa_t *this)
 			continue;
 		}
 		DBG1(DBG_IKE, "looking for a route to %H ...", addr);
-		src = hydra->kernel_interface->get_source_addr(
-										hydra->kernel_interface, addr, NULL);
+		src = charon->kernel->get_source_addr(charon->kernel, addr, NULL);
 		if (src)
 		{
 			break;
@@ -2323,7 +2686,7 @@ METHOD(ike_sa_t, inherit_post, void,
 	this->conditions = other->conditions;
 	if (this->conditions & COND_NAT_HERE)
 	{
-		send_keepalive(this);
+		send_keepalive(this, FALSE);
 	}
 
 #ifdef ME
@@ -2401,7 +2764,7 @@ METHOD(ike_sa_t, destroy, void,
 	}
 	while (array_remove(this->my_vips, ARRAY_TAIL, &vip))
 	{
-		hydra->kernel_interface->del_ip(hydra->kernel_interface, vip, -1, TRUE);
+		charon->kernel->del_ip(charon->kernel, vip, -1, TRUE);
 		vip->destroy(vip);
 	}
 	if (array_count(this->other_vips))
@@ -2450,6 +2813,8 @@ METHOD(ike_sa_t, destroy, void,
 	DESTROY_IF(this->other_id);
 	DESTROY_IF(this->local_host);
 	DESTROY_IF(this->remote_host);
+	DESTROY_IF(this->redirected_from);
+	array_destroy(this->redirected_at);
 
 	DESTROY_IF(this->ike_cfg);
 	DESTROY_IF(this->peer_cfg);
@@ -2498,6 +2863,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
 			.set_peer_cfg = _set_peer_cfg,
 			.get_auth_cfg = _get_auth_cfg,
 			.create_auth_cfg_enumerator = _create_auth_cfg_enumerator,
+			.verify_peer_certificate = _verify_peer_certificate,
 			.add_auth_cfg = _add_auth_cfg,
 			.get_proposal = _get_proposal,
 			.set_proposal = _set_proposal,
@@ -2529,6 +2895,9 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
 			.destroy = _destroy,
 			.send_dpd = _send_dpd,
 			.send_keepalive = _send_keepalive,
+			.redirect = _redirect,
+			.handle_redirect = _handle_redirect,
+			.get_redirected_from = _get_redirected_from,
 			.get_keymat = _get_keymat,
 			.add_child_sa = _add_child_sa,
 			.get_child_sa = _get_child_sa,
@@ -2594,6 +2963,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
 								"%s.flush_auth_cfg", FALSE, lib->ns),
 		.fragment_size = lib->settings->get_int(lib->settings,
 								"%s.fragment_size", 0, lib->ns),
+		.follow_redirects = lib->settings->get_bool(lib->settings,
+								"%s.follow_redirects", TRUE, lib->ns),
 	);
 
 	if (version == IKEV2)
diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h
index 9dbc805..836360e 100644
--- a/src/libcharon/sa/ike_sa.h
+++ b/src/libcharon/sa/ike_sa.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2014 Tobias Brunner
+ * Copyright (C) 2006-2015 Tobias Brunner
  * Copyright (C) 2006 Daniel Roethlisberger
  * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
@@ -66,6 +66,16 @@ typedef struct ike_sa_t ike_sa_t;
 #define RETRY_JITTER 20
 
 /**
+ * Number of redirects allowed within REDIRECT_LOOP_DETECT_PERIOD.
+ */
+#define MAX_REDIRECTS 5
+
+/**
+ * Time period in seconds in which at most MAX_REDIRECTS are allowed.
+ */
+#define REDIRECT_LOOP_DETECT_PERIOD 300
+
+/**
  * Extensions (or optional features) the peer supports
  */
 enum ike_extension_t {
@@ -136,6 +146,11 @@ enum ike_extension_t {
 	 * Signature Authentication, RFC 7427
 	 */
 	EXT_SIGNATURE_AUTH = (1<<12),
+
+	/**
+	 * IKEv2 Redirect Mechanism, RFC 5685
+	 */
+	EXT_IKE_REDIRECTION = (1<<13),
 };
 
 /**
@@ -197,6 +212,16 @@ enum ike_condition_t {
 	 * This IKE_SA is currently being reauthenticated
 	 */
 	COND_REAUTHENTICATING = (1<<10),
+
+	/**
+	 * This IKE_SA has been redirected
+	 */
+	COND_REDIRECTED = (1<<11),
+
+	/**
+	 * Online certificate revocation checking is suspended for this IKE_SA
+	 */
+	COND_ONLINE_VALIDATION_SUSPENDED = (1<<12),
 };
 
 /**
@@ -502,6 +527,14 @@ struct ike_sa_t {
 	enumerator_t* (*create_auth_cfg_enumerator)(ike_sa_t *this, bool local);
 
 	/**
+	 * Verify the trustchains (validity, revocation) in completed public key
+	 * auth rounds.
+	 *
+	 * @return				TRUE if certificates were valid, FALSE otherwise
+	 */
+	bool (*verify_peer_certificate)(ike_sa_t *this);
+
+	/**
 	 * Get the selected proposal of this IKE_SA.
 	 *
 	 * @return				selected proposal
@@ -837,8 +870,36 @@ struct ike_sa_t {
 	 *
 	 * To refresh NAT tables in a NAT router between the peers, periodic empty
 	 * UDP packets are sent if no other traffic was sent.
+	 *
+	 * @param scheduled		if this is a scheduled keepalive
+	 */
+	void (*send_keepalive) (ike_sa_t *this, bool scheduled);
+
+	/**
+	 * Redirect an active IKE_SA.
+	 *
+	 * @param gateway		gateway ID (IP or FQDN) of the target
+	 * @return				state, including DESTROY_ME, if this IKE_SA MUST be
+	 * 						destroyed
+	 */
+	status_t (*redirect)(ike_sa_t *this, identification_t *gateway);
+
+	/**
+	 * Handle a redirect request.
+	 *
+	 * The behavior is different depending on the state of the IKE_SA.
+	 *
+	 * @param gateway		gateway ID (IP or FQDN) of the target
+	 * @return				FALSE if redirect not possible, TRUE otherwise
+	 */
+	bool (*handle_redirect)(ike_sa_t *this, identification_t *gateway);
+
+	/**
+	 * Get the address of the gateway that redirected us.
+	 *
+	 * @return				original gateway address
 	 */
-	void (*send_keepalive) (ike_sa_t *this);
+	host_t *(*get_redirected_from)(ike_sa_t *this);
 
 	/**
 	 * Get the keying material of this IKE_SA.
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index 4625df5..307ea3b 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2005-2011 Martin Willi
  * Copyright (C) 2011 revosec AG
- * Copyright (C) 2008-2015 Tobias Brunner
+ * Copyright (C) 2008-2016 Tobias Brunner
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
  *
@@ -17,12 +17,14 @@
  */
 
 #include <string.h>
+#include <inttypes.h>
 
 #include "ike_sa_manager.h"
 
 #include <daemon.h>
 #include <sa/ike_sa_id.h>
 #include <bus/bus.h>
+#include <threading/thread.h>
 #include <threading/condvar.h>
 #include <threading/mutex.h>
 #include <threading/rwlock.h>
@@ -57,9 +59,9 @@ struct entry_t {
 	condvar_t *condvar;
 
 	/**
-	 * Is this ike_sa currently checked out?
+	 * Thread by which this IKE_SA is currently checked out, if any
 	 */
-	bool checked_out;
+	thread_t *checked_out;
 
 	/**
 	 * Does this SA drives out new threads?
@@ -1142,13 +1144,16 @@ METHOD(ike_sa_manager_t, checkout, ike_sa_t*,
 	entry_t *entry;
 	u_int segment;
 
-	DBG2(DBG_MGR, "checkout IKE_SA");
+	DBG2(DBG_MGR, "checkout %N SA with SPIs %.16"PRIx64"_i %.16"PRIx64"_r",
+		 ike_version_names, ike_sa_id->get_ike_version(ike_sa_id),
+		 be64toh(ike_sa_id->get_initiator_spi(ike_sa_id)),
+		 be64toh(ike_sa_id->get_responder_spi(ike_sa_id)));
 
 	if (get_entry_by_id(this, ike_sa_id, &entry, &segment) == SUCCESS)
 	{
 		if (wait_for_entry(this, entry, segment))
 		{
-			entry->checked_out = TRUE;
+			entry->checked_out = thread_current();
 			ike_sa = entry->ike_sa;
 			DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out",
 					ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
@@ -1156,6 +1161,11 @@ METHOD(ike_sa_manager_t, checkout, ike_sa_t*,
 		unlock_single_segment(this, segment);
 	}
 	charon->bus->set_sa(charon->bus, ike_sa);
+
+	if (!ike_sa)
+	{
+		DBG2(DBG_MGR, "IKE_SA checkout not successful");
+	}
 	return ike_sa;
 }
 
@@ -1228,7 +1238,10 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
 	id = id->clone(id);
 	id->switch_initiator(id);
 
-	DBG2(DBG_MGR, "checkout IKE_SA by message");
+	DBG2(DBG_MGR, "checkout %N SA by message with SPIs %.16"PRIx64"_i "
+		 "%.16"PRIx64"_r", ike_version_names, id->get_ike_version(id),
+		 be64toh(id->get_initiator_spi(id)),
+		 be64toh(id->get_responder_spi(id)));
 
 	if (id->get_responder_spi(id) == 0 &&
 		message->get_message_id(message) == 0)
@@ -1269,7 +1282,7 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
 			DBG1(DBG_MGR, "ignoring message, failed to hash message");
 			DESTROY_IF(hasher);
 			id->destroy(id);
-			return NULL;
+			goto out;
 		}
 		hasher->destroy(hasher);
 
@@ -1288,20 +1301,17 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
 						entry = entry_create();
 						entry->ike_sa = ike_sa;
 						entry->ike_sa_id = id;
+						entry->processing = get_message_id_or_hash(message);
+						entry->init_hash = hash;
 
 						segment = put_entry(this, entry);
-						entry->checked_out = TRUE;
+						entry->checked_out = thread_current();
 						unlock_single_segment(this, segment);
 
-						entry->processing = get_message_id_or_hash(message);
-						entry->init_hash = hash;
-
 						DBG2(DBG_MGR, "created IKE_SA %s[%u]",
 							 ike_sa->get_name(ike_sa),
 							 ike_sa->get_unique_id(ike_sa));
-
-						charon->bus->set_sa(charon->bus, ike_sa);
-						return ike_sa;
+						goto out;
 					}
 					else
 					{
@@ -1317,14 +1327,14 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
 				remove_init_hash(this, hash);
 				chunk_free(&hash);
 				id->destroy(id);
-				return NULL;
+				goto out;
 			}
 			case FAILED:
 			{	/* we failed to allocate an SPI */
 				chunk_free(&hash);
 				id->destroy(id);
 				DBG1(DBG_MGR, "ignoring message, failed to allocate SPI");
-				return NULL;
+				goto out;
 			}
 			case ALREADY_DONE:
 			default:
@@ -1348,7 +1358,7 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
 			ike_sa_id_t *ike_id;
 
 			ike_id = entry->ike_sa->get_id(entry->ike_sa);
-			entry->checked_out = TRUE;
+			entry->checked_out = thread_current();
 			if (message->get_first_payload_type(message) != PLV1_FRAGMENT &&
 				message->get_first_payload_type(message) != PLV2_FRAGMENT)
 			{	/* TODO-FRAG: this fails if there are unencrypted payloads */
@@ -1369,7 +1379,13 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
 		charon->bus->alert(charon->bus, ALERT_INVALID_IKE_SPI, message);
 	}
 	id->destroy(id);
+
+out:
 	charon->bus->set_sa(charon->bus, ike_sa);
+	if (!ike_sa)
+	{
+		DBG2(DBG_MGR, "IKE_SA checkout not successful");
+	}
 	return ike_sa;
 }
 
@@ -1385,11 +1401,11 @@ METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*,
 
 	DBG2(DBG_MGR, "checkout IKE_SA by config");
 
-	if (!this->reuse_ikesa)
-	{	/* IKE_SA reuse disable by config */
+	if (!this->reuse_ikesa && peer_cfg->get_ike_version(peer_cfg) != IKEV1)
+	{	/* IKE_SA reuse disabled by config (not possible for IKEv1) */
 		ike_sa = checkout_new(this, peer_cfg->get_ike_version(peer_cfg), TRUE);
 		charon->bus->set_sa(charon->bus, ike_sa);
-		return ike_sa;
+		goto out;
 	}
 
 	enumerator = create_table_enumerator(this);
@@ -1411,7 +1427,7 @@ METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*,
 			current_ike = current_peer->get_ike_cfg(current_peer);
 			if (current_ike->equals(current_ike, peer_cfg->get_ike_cfg(peer_cfg)))
 			{
-				entry->checked_out = TRUE;
+				entry->checked_out = thread_current();
 				ike_sa = entry->ike_sa;
 				DBG2(DBG_MGR, "found existing IKE_SA %u with a '%s' config",
 						ike_sa->get_unique_id(ike_sa),
@@ -1429,6 +1445,12 @@ METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*,
 		ike_sa = checkout_new(this, peer_cfg->get_ike_version(peer_cfg), TRUE);
 	}
 	charon->bus->set_sa(charon->bus, ike_sa);
+
+out:
+	if (!ike_sa)
+	{
+		DBG2(DBG_MGR, "IKE_SA checkout not successful");
+	}
 	return ike_sa;
 }
 
@@ -1440,7 +1462,7 @@ METHOD(ike_sa_manager_t, checkout_by_id, ike_sa_t*,
 	ike_sa_t *ike_sa = NULL;
 	u_int segment;
 
-	DBG2(DBG_MGR, "checkout IKE_SA by ID %u", id);
+	DBG2(DBG_MGR, "checkout IKE_SA by unique ID %u", id);
 
 	enumerator = create_table_enumerator(this);
 	while (enumerator->enumerate(enumerator, &entry, &segment))
@@ -1450,7 +1472,7 @@ METHOD(ike_sa_manager_t, checkout_by_id, ike_sa_t*,
 			if (entry->ike_sa->get_unique_id(entry->ike_sa) == id)
 			{
 				ike_sa = entry->ike_sa;
-				entry->checked_out = TRUE;
+				entry->checked_out = thread_current();
 				break;
 			}
 			/* other threads might be waiting for this entry */
@@ -1464,6 +1486,10 @@ METHOD(ike_sa_manager_t, checkout_by_id, ike_sa_t*,
 		DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out",
 			 ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
 	}
+	else
+	{
+		DBG2(DBG_MGR, "IKE_SA checkout not successful");
+	}
 	charon->bus->set_sa(charon->bus, ike_sa);
 	return ike_sa;
 }
@@ -1477,6 +1503,8 @@ METHOD(ike_sa_manager_t, checkout_by_name, ike_sa_t*,
 	child_sa_t *child_sa;
 	u_int segment;
 
+	DBG2(DBG_MGR, "checkout IKE_SA by%s name '%s'", child ? " child" : "", name);
+
 	enumerator = create_table_enumerator(this);
 	while (enumerator->enumerate(enumerator, &entry, &segment))
 	{
@@ -1506,7 +1534,7 @@ METHOD(ike_sa_manager_t, checkout_by_name, ike_sa_t*,
 			/* got one, return */
 			if (ike_sa)
 			{
-				entry->checked_out = TRUE;
+				entry->checked_out = thread_current();
 				DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out",
 						ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
 				break;
@@ -1518,6 +1546,11 @@ METHOD(ike_sa_manager_t, checkout_by_name, ike_sa_t*,
 	enumerator->destroy(enumerator);
 
 	charon->bus->set_sa(charon->bus, ike_sa);
+
+	if (!ike_sa)
+	{
+		DBG2(DBG_MGR, "IKE_SA checkout not successful");
+	}
 	return ike_sa;
 }
 
@@ -1598,7 +1631,7 @@ METHOD(ike_sa_manager_t, checkin, void,
 		/* ike_sa_id must be updated */
 		entry->ike_sa_id->replace_values(entry->ike_sa_id, ike_sa->get_id(ike_sa));
 		/* signal waiting threads */
-		entry->checked_out = FALSE;
+		entry->checked_out = NULL;
 		entry->processing = -1;
 		/* check if this SA is half-open */
 		if (entry->half_open && ike_sa->get_state(ike_sa) != IKE_CONNECTING)
@@ -1623,7 +1656,6 @@ METHOD(ike_sa_manager_t, checkin, void,
 			entry->other = other->clone(other);
 			put_half_open(this, entry);
 		}
-		DBG2(DBG_MGR, "check-in of IKE_SA successful.");
 		entry->condvar->signal(entry->condvar);
 	}
 	else
@@ -1639,6 +1671,7 @@ METHOD(ike_sa_manager_t, checkin, void,
 		}
 		segment = put_entry(this, entry);
 	}
+	DBG2(DBG_MGR, "checkin of IKE_SA successful");
 
 	/* apply identities for duplicate test */
 	if ((ike_sa->get_state(ike_sa) == IKE_ESTABLISHED ||
@@ -1657,7 +1690,7 @@ METHOD(ike_sa_manager_t, checkin, void,
 				 * thread can acquire it.  Since it is not yet in the list of
 				 * connected peers that will not cause a deadlock as no other
 				 * caller of check_unqiueness() will try to check out this SA */
-				entry->checked_out = TRUE;
+				entry->checked_out = thread_current();
 				unlock_single_segment(this, segment);
 
 				this->public.check_uniqueness(&this->public, ike_sa, TRUE);
@@ -1668,7 +1701,7 @@ METHOD(ike_sa_manager_t, checkin, void,
 				 * thread is waiting, but it should still exist, so there is no
 				 * need for a lookup via get_entry_by... */
 				lock_single_segment(this, segment);
-				entry->checked_out = FALSE;
+				entry->checked_out = NULL;
 				/* We already signaled waiting threads above, we have to do that
 				 * again after checking the SA out and back in again. */
 				entry->condvar->signal(entry->condvar);
@@ -1711,8 +1744,8 @@ METHOD(ike_sa_manager_t, checkin_and_destroy, void,
 		if (entry->driveout_waiting_threads && entry->driveout_new_threads)
 		{	/* it looks like flush() has been called and the SA is being deleted
 			 * anyway, just check it in */
-			DBG2(DBG_MGR, "ignored check-in and destroy of IKE_SA during shutdown");
-			entry->checked_out = FALSE;
+			DBG2(DBG_MGR, "ignored checkin and destroy of IKE_SA during shutdown");
+			entry->checked_out = NULL;
 			entry->condvar->broadcast(entry->condvar);
 			unlock_single_segment(this, segment);
 			return;
@@ -1748,11 +1781,11 @@ METHOD(ike_sa_manager_t, checkin_and_destroy, void,
 
 		entry_destroy(entry);
 
-		DBG2(DBG_MGR, "check-in and destroy of IKE_SA successful");
+		DBG2(DBG_MGR, "checkin and destroy of IKE_SA successful");
 	}
 	else
 	{
-		DBG1(DBG_MGR, "tried to check-in and delete nonexisting IKE_SA");
+		DBG1(DBG_MGR, "tried to checkin and delete nonexisting IKE_SA");
 		ike_sa->destroy(ike_sa);
 	}
 	charon->bus->set_sa(charon->bus, NULL);
diff --git a/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c b/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c
index 52228ef..eee7dd1 100644
--- a/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c
+++ b/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c
@@ -173,13 +173,13 @@ METHOD(authenticator_t, process, status_t,
 	sig = sig_payload->get_hash(sig_payload);
 	auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
 	enumerator = lib->credmgr->create_public_enumerator(lib->credmgr, this->type,
-														id, auth);
+														id, auth, TRUE);
 	while (enumerator->enumerate(enumerator, &public, &current_auth))
 	{
 		if (public->verify(public, scheme, hash, sig))
 		{
 			DBG1(DBG_IKE, "authentication of '%Y' with %N successful",
-				 id, key_type_names, this->type);
+				 id, signature_scheme_names, scheme);
 			status = SUCCESS;
 			auth->merge(auth, current_auth, FALSE);
 			auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
diff --git a/src/libcharon/sa/ikev1/phase1.c b/src/libcharon/sa/ikev1/phase1.c
index b7047e8..c968b2a 100644
--- a/src/libcharon/sa/ikev1/phase1.c
+++ b/src/libcharon/sa/ikev1/phase1.c
@@ -404,7 +404,7 @@ static auth_method_t get_pubkey_method(private_phase1_t *this, auth_cfg_t *auth)
 		id = (identification_t*)auth->get(auth, AUTH_RULE_IDENTITY);
 		if (id)
 		{
-			private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, id, auth);
+			private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, id, NULL);
 			if (private)
 			{
 				switch (private->get_type(private))
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_natd.c b/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
index b8af6f6..cb1a313 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
@@ -41,7 +41,6 @@
 
 #include <string.h>
 
-#include <hydra.h>
 #include <daemon.h>
 #include <sa/ikev1/keymat_v1.h>
 #include <config/peer_cfg.h>
@@ -104,7 +103,7 @@ static bool force_encap(ike_cfg_t *ike_cfg)
 {
 	if (!ike_cfg->force_encap(ike_cfg))
 	{
-		return hydra->kernel_interface->get_features(hydra->kernel_interface) &
+		return charon->kernel->get_features(charon->kernel) &
 					KERNEL_REQUIRE_UDP_ENCAPSULATION;
 	}
 	return TRUE;
diff --git a/src/libcharon/sa/ikev1/tasks/mode_config.c b/src/libcharon/sa/ikev1/tasks/mode_config.c
index a03477e..b9f9240 100644
--- a/src/libcharon/sa/ikev1/tasks/mode_config.c
+++ b/src/libcharon/sa/ikev1/tasks/mode_config.c
@@ -76,35 +76,20 @@ typedef struct {
  */
 static configuration_attribute_t *build_vip(host_t *vip)
 {
-	configuration_attribute_type_t type;
-	chunk_t chunk, prefix;
+	configuration_attribute_type_t type = INTERNAL_IP4_ADDRESS;
+	chunk_t chunk;
 
-	if (vip->get_family(vip) == AF_INET)
+	if (vip->get_family(vip) == AF_INET6)
 	{
-		type = INTERNAL_IP4_ADDRESS;
-		if (vip->is_anyaddr(vip))
-		{
-			chunk = chunk_empty;
-		}
-		else
-		{
-			chunk = vip->get_address(vip);
-		}
+		type = INTERNAL_IP6_ADDRESS;
+	}
+	if (vip->is_anyaddr(vip))
+	{
+		chunk = chunk_empty;
 	}
 	else
 	{
-		type = INTERNAL_IP6_ADDRESS;
-		if (vip->is_anyaddr(vip))
-		{
-			chunk = chunk_empty;
-		}
-		else
-		{
-			prefix = chunk_alloca(1);
-			*prefix.ptr = 64;
-			chunk = vip->get_address(vip);
-			chunk = chunk_cata("cc", chunk, prefix);
-		}
+		chunk = vip->get_address(vip);
 	}
 	return configuration_attribute_create_chunk(PLV1_CONFIGURATION_ATTRIBUTE,
 												type, chunk);
@@ -165,8 +150,8 @@ static void process_attribute(private_mode_config_t *this,
 			}
 			else
 			{
-				/* skip prefix byte in IPv6 payload*/
-				if (family == AF_INET6)
+				/* skip prefix byte in IPv6 payload sent by older releases */
+				if (family == AF_INET6 && addr.len == 17)
 				{
 					addr.len--;
 				}
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c
index e7d2644..b4fe046 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c
@@ -171,6 +171,11 @@ struct private_quick_mode_t {
 	u_int32_t rekey;
 
 	/**
+	 * Delete old child after successful rekey
+	 */
+	bool delete;
+
+	/**
 	 * Negotiated mode, tunnel or transport
 	 */
 	ipsec_mode_t mode;
@@ -406,8 +411,17 @@ static bool install(private_quick_mode_t *this)
 	if (old)
 	{
 		charon->bus->child_rekey(charon->bus, old, this->child_sa);
-		/* rekeyed CHILD_SAs stay installed until they expire */
+		/* rekeyed CHILD_SAs stay installed until they expire or are deleted
+		 * by the other peer */
 		old->set_state(old, CHILD_REKEYED);
+		/* as initiator we delete the CHILD_SA if configured to do so */
+		if (this->initiator && this->delete)
+		{
+			this->ike_sa->queue_task(this->ike_sa,
+				(task_t*)quick_delete_create(this->ike_sa,
+								this->proposal->get_protocol(this->proposal),
+								this->rekey, TRUE, FALSE));
+		}
 	}
 	else
 	{
@@ -1450,6 +1464,8 @@ quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
 		.tsi = tsi ? tsi->clone(tsi) : NULL,
 		.tsr = tsr ? tsr->clone(tsr) : NULL,
 		.proto = PROTO_ESP,
+		.delete = lib->settings->get_bool(lib->settings,
+										  "%s.delete_rekeyed", FALSE, lib->ns),
 	);
 
 	if (config)
diff --git a/src/libcharon/sa/ikev1/tasks/xauth.c b/src/libcharon/sa/ikev1/tasks/xauth.c
index c0c9157..ecdfc78 100644
--- a/src/libcharon/sa/ikev1/tasks/xauth.c
+++ b/src/libcharon/sa/ikev1/tasks/xauth.c
@@ -16,7 +16,6 @@
 #include "xauth.h"
 
 #include <daemon.h>
-#include <hydra.h>
 #include <encoding/payloads/cp_payload.h>
 #include <processing/jobs/adopt_children_job.h>
 #include <sa/ikev1/tasks/mode_config.h>
diff --git a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
index 2284a48..04ccd4f 100644
--- a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
@@ -55,11 +55,6 @@ struct private_pubkey_authenticator_t {
 	 * Reserved bytes of ID payload
 	 */
 	char reserved[3];
-
-	/**
-	 * Whether to store signature schemes on remote auth configs.
-	 */
-	bool store_signature_scheme;
 };
 
 /**
@@ -130,7 +125,7 @@ static array_t *select_signature_schemes(keymat_v2_t *keymat,
 	enumerator = auth->create_enumerator(auth);
 	while (enumerator->enumerate(enumerator, &rule, &config))
 	{
-		if (rule != AUTH_RULE_SIGNATURE_SCHEME)
+		if (rule != AUTH_RULE_IKE_SIGNATURE_SCHEME)
 		{
 			continue;
 		}
@@ -369,6 +364,8 @@ METHOD(authenticator_t, process, status_t,
 	signature_scheme_t scheme;
 	status_t status = NOT_FOUND;
 	keymat_v2_t *keymat;
+	const char *reason = "unsupported";
+	bool online;
 
 	auth_payload = (auth_payload_t*)message->get_payload(message, PLV2_AUTH);
 	if (!auth_payload)
@@ -397,8 +394,11 @@ METHOD(authenticator_t, process, status_t,
 			{
 				break;
 			}
+			reason = "payload invalid";
 			/* fall-through */
 		default:
+			DBG1(DBG_IKE, "%N authentication %s", auth_method_names,
+				 auth_method, reason);
 			return INVALID_ARG;
 	}
 	id = this->ike_sa->get_other_id(this->ike_sa);
@@ -409,8 +409,10 @@ METHOD(authenticator_t, process, status_t,
 		return FAILED;
 	}
 	auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
+	online = !this->ike_sa->has_condition(this->ike_sa,
+										  COND_ONLINE_VALIDATION_SUSPENDED);
 	enumerator = lib->credmgr->create_public_enumerator(lib->credmgr,
-														key_type, id, auth);
+													key_type, id, auth, online);
 	while (enumerator->enumerate(enumerator, &public, &current_auth))
 	{
 		if (public->verify(public, scheme, octets, auth_data))
@@ -421,9 +423,10 @@ METHOD(authenticator_t, process, status_t,
 			status = SUCCESS;
 			auth->merge(auth, current_auth, FALSE);
 			auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
-			if (this->store_signature_scheme)
+			auth->add(auth, AUTH_RULE_IKE_SIGNATURE_SCHEME, (uintptr_t)scheme);
+			if (!online)
 			{
-				auth->add(auth, AUTH_RULE_SIGNATURE_SCHEME, (uintptr_t)scheme);
+				auth->add(auth, AUTH_RULE_CERT_VALIDATION_SUSPENDED, TRUE);
 			}
 			break;
 		}
@@ -497,8 +500,6 @@ pubkey_authenticator_t *pubkey_authenticator_create_verifier(ike_sa_t *ike_sa,
 		.ike_sa = ike_sa,
 		.ike_sa_init = received_init,
 		.nonce = sent_nonce,
-		.store_signature_scheme = lib->settings->get_bool(lib->settings,
-					"%s.signature_authentication_constraints", TRUE, lib->ns),
 	);
 	memcpy(this->reserved, reserved, sizeof(this->reserved));
 
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index 4676867..c2f972a 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2014 Tobias Brunner
+ * Copyright (C) 2007-2015 Tobias Brunner
  * Copyright (C) 2007-2010 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -30,10 +30,12 @@
 #include <sa/ikev2/tasks/ike_rekey.h>
 #include <sa/ikev2/tasks/ike_reauth.h>
 #include <sa/ikev2/tasks/ike_reauth_complete.h>
+#include <sa/ikev2/tasks/ike_redirect.h>
 #include <sa/ikev2/tasks/ike_delete.h>
 #include <sa/ikev2/tasks/ike_config.h>
 #include <sa/ikev2/tasks/ike_dpd.h>
 #include <sa/ikev2/tasks/ike_vendor.h>
+#include <sa/ikev2/tasks/ike_verify_peer_cert.h>
 #include <sa/ikev2/tasks/child_create.h>
 #include <sa/ikev2/tasks/child_rekey.h>
 #include <sa/ikev2/tasks/child_delete.h>
@@ -474,6 +476,11 @@ METHOD(task_manager_t, initiate, status_t,
 					exchange = INFORMATIONAL;
 					break;
 				}
+				if (activate_task(this, TASK_IKE_REDIRECT))
+				{
+					exchange = INFORMATIONAL;
+					break;
+				}
 				if (activate_task(this, TASK_CHILD_DELETE))
 				{
 					exchange = INFORMATIONAL;
@@ -521,6 +528,11 @@ METHOD(task_manager_t, initiate, status_t,
 					exchange = INFORMATIONAL;
 					break;
 				}
+				if (activate_task(this, TASK_IKE_VERIFY_PEER_CERT))
+				{
+					exchange = INFORMATIONAL;
+					break;
+				}
 			case IKE_REKEYING:
 				if (activate_task(this, TASK_IKE_DELETE))
 				{
@@ -618,7 +630,7 @@ METHOD(task_manager_t, initiate, status_t,
 	if (this->initiating.type == EXCHANGE_TYPE_UNDEFINED)
 	{
 		message->destroy(message);
-		return SUCCESS;
+		return initiate(this);
 	}
 
 	if (!generate_message(this, message, &this->initiating.packets))
@@ -656,6 +668,32 @@ static status_t process_response(private_task_manager_t *this,
 		return DESTROY_ME;
 	}
 
+	enumerator = array_create_enumerator(this->active_tasks);
+	while (enumerator->enumerate(enumerator, &task))
+	{
+		if (!task->pre_process)
+		{
+			continue;
+		}
+		switch (task->pre_process(task, message))
+		{
+			case SUCCESS:
+				break;
+			case FAILED:
+			default:
+				/* just ignore the message */
+				DBG1(DBG_IKE, "ignore invalid %N response",
+					 exchange_type_names, message->get_exchange_type(message));
+				enumerator->destroy(enumerator);
+				return SUCCESS;
+			case DESTROY_ME:
+				/* critical failure, destroy IKE_SA */
+				enumerator->destroy(enumerator);
+				return DESTROY_ME;
+		}
+	}
+	enumerator->destroy(enumerator);
+
 	/* catch if we get resetted while processing */
 	this->reset = FALSE;
 	enumerator = array_create_enumerator(this->active_tasks);
@@ -992,6 +1030,11 @@ static status_t process_request(private_task_manager_t *this,
 									 * invokes all the required hooks. */
 									task = (task_t*)ike_delete_create(
 														this->ike_sa, FALSE);
+									break;
+								case REDIRECT:
+									task = (task_t*)ike_redirect_create(
+															this->ike_sa, NULL);
+									break;
 								default:
 									break;
 							}
@@ -1041,6 +1084,44 @@ static status_t process_request(private_task_manager_t *this,
 		}
 	}
 
+	enumerator = array_create_enumerator(this->passive_tasks);
+	while (enumerator->enumerate(enumerator, &task))
+	{
+		if (!task->pre_process)
+		{
+			continue;
+		}
+		switch (task->pre_process(task, message))
+		{
+			case SUCCESS:
+				break;
+			case FAILED:
+			default:
+				/* just ignore the message */
+				DBG1(DBG_IKE, "ignore invalid %N request",
+					 exchange_type_names, message->get_exchange_type(message));
+				enumerator->destroy(enumerator);
+				switch (message->get_exchange_type(message))
+				{
+					case IKE_SA_INIT:
+						/* no point in keeping the SA when it was created with
+						 * an invalid IKE_SA_INIT message */
+						return DESTROY_ME;
+					default:
+						/* remove tasks we queued for this request */
+						flush_queue(this, TASK_QUEUE_PASSIVE);
+						/* fall-through */
+					case IKE_AUTH:
+						return NEED_MORE;
+				}
+			case DESTROY_ME:
+				/* critical failure, destroy IKE_SA */
+				enumerator->destroy(enumerator);
+				return DESTROY_ME;
+		}
+	}
+	enumerator->destroy(enumerator);
+
 	/* let the tasks process the message */
 	enumerator = array_create_enumerator(this->passive_tasks);
 	while (enumerator->enumerate(enumerator, (void*)&task))
@@ -1331,12 +1412,17 @@ METHOD(task_manager_t, process_message, status_t,
 			{	/* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
 				return SUCCESS;
 			}
-			if (process_request(this, msg) != SUCCESS)
+			switch (process_request(this, msg))
 			{
-				flush(this);
-				return DESTROY_ME;
+				case SUCCESS:
+					this->responding.mid++;
+					break;
+				case NEED_MORE:
+					break;
+				default:
+					flush(this);
+					return DESTROY_ME;
 			}
-			this->responding.mid++;
 		}
 		else if ((mid == this->responding.mid - 1) &&
 				 array_count(this->responding.packets))
@@ -1570,8 +1656,12 @@ static void trigger_mbb_reauth(private_task_manager_t *this)
 	}
 	enumerator->destroy(enumerator);
 
+	/* suspend online revocation checking until the SA is established */
+	new->set_condition(new, COND_ONLINE_VALIDATION_SUSPENDED, TRUE);
+
 	if (new->initiate(new, NULL, 0, NULL, NULL) != DESTROY_ME)
 	{
+		new->queue_task(new, (task_t*)ike_verify_peer_cert_create(new));
 		new->queue_task(new, (task_t*)ike_reauth_complete_create(new,
 										this->ike_sa->get_id(this->ike_sa)));
 		charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c
index 97f73d8..3d4ded9 100644
--- a/src/libcharon/sa/ikev2/tasks/child_create.c
+++ b/src/libcharon/sa/ikev2/tasks/child_create.c
@@ -18,7 +18,6 @@
 #include "child_create.h"
 
 #include <daemon.h>
-#include <hydra.h>
 #include <sa/ikev2/keymat_v2.h>
 #include <crypto/diffie_hellman.h>
 #include <credentials/certificates/x509.h>
@@ -786,7 +785,7 @@ static bool build_payloads(private_child_create_t *this, message_t *message)
 			break;
 	}
 
-	features = hydra->kernel_interface->get_features(hydra->kernel_interface);
+	features = charon->kernel->get_features(charon->kernel);
 	if (!(features & KERNEL_ESP_V3_TFC))
 	{
 		message->add_notify(message, FALSE, ESP_TFC_PADDING_NOT_SUPPORTED,
@@ -1221,6 +1220,10 @@ METHOD(task_t, build_r, status_t,
 			{	/* wait until all authentication round completed */
 				return NEED_MORE;
 			}
+			if (this->ike_sa->has_condition(this->ike_sa, COND_REDIRECTED))
+			{	/* no CHILD_SA is created for redirected SAs */
+				return SUCCESS;
+			}
 			ike_auth = TRUE;
 		default:
 			break;
diff --git a/src/libcharon/sa/ikev2/tasks/child_rekey.c b/src/libcharon/sa/ikev2/tasks/child_rekey.c
index c7a8a13..6f0c2b2 100644
--- a/src/libcharon/sa/ikev2/tasks/child_rekey.c
+++ b/src/libcharon/sa/ikev2/tasks/child_rekey.c
@@ -279,11 +279,15 @@ static child_sa_t *handle_collision(private_child_rekey_t *this)
 			/* don't touch child other created, it has already been deleted */
 			if (!this->other_child_destroyed)
 			{
-				/* disable close action for the redundand child */
+				/* disable close action and updown event for redundant child */
 				child_sa = other->child_create->get_child(other->child_create);
 				if (child_sa)
 				{
 					child_sa->set_close_action(child_sa, ACTION_NONE);
+					if (child_sa->get_state(child_sa) != CHILD_REKEYING)
+					{
+						child_sa->set_state(child_sa, CHILD_REKEYING);
+					}
 				}
 			}
 		}
@@ -372,6 +376,11 @@ METHOD(task_t, process_i, status_t,
 	{
 		return SUCCESS;
 	}
+	/* disable updown event for redundant CHILD_SA */
+	if (to_delete->get_state(to_delete) != CHILD_REKEYING)
+	{
+		to_delete->set_state(to_delete, CHILD_REKEYING);
+	}
 	spi = to_delete->get_spi(to_delete, TRUE);
 	protocol = to_delete->get_protocol(to_delete);
 
diff --git a/src/libcharon/sa/ikev2/tasks/ike_auth.c b/src/libcharon/sa/ikev2/tasks/ike_auth.c
index 2554496..79a436f 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_auth.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_auth.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012-2015 Tobias Brunner
  * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
@@ -25,6 +25,7 @@
 #include <encoding/payloads/eap_payload.h>
 #include <encoding/payloads/nonce_payload.h>
 #include <sa/ikev2/authenticators/eap_authenticator.h>
+#include <processing/jobs/delete_ike_sa_job.h>
 
 typedef struct private_ike_auth_t private_ike_auth_t;
 
@@ -117,6 +118,11 @@ struct private_ike_auth_t {
 	 * Is EAP acceptable, did we strictly authenticate peer?
 	 */
 	bool eap_acceptable;
+
+	/**
+	 * Gateway ID if redirected
+	 */
+	identification_t *redirect_to;
 };
 
 /**
@@ -685,6 +691,7 @@ METHOD(task_t, process_r, status_t,
 METHOD(task_t, build_r, status_t,
 	private_ike_auth_t *this, message_t *message)
 {
+	identification_t *gateway;
 	auth_cfg_t *cfg;
 
 	if (message->get_exchange_type(message) == IKE_SA_INIT)
@@ -817,34 +824,56 @@ METHOD(task_t, build_r, status_t,
 	{
 		this->do_another_auth = FALSE;
 	}
-	if (!this->do_another_auth && !this->expect_another_auth)
+	if (this->do_another_auth || this->expect_another_auth)
 	{
-		if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
-													 this->ike_sa, FALSE))
-		{
-			DBG1(DBG_IKE, "cancelling IKE_SA setup due to uniqueness policy");
-			charon->bus->alert(charon->bus, ALERT_UNIQUE_KEEP);
-			message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
-								chunk_empty);
-			return FAILED;
-		}
-		if (!charon->bus->authorize(charon->bus, TRUE))
-		{
-			DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
-			goto peer_auth_failed;
-		}
-		DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
-			 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->set_state(this->ike_sa, IKE_ESTABLISHED);
-		charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
-		return SUCCESS;
+		return NEED_MORE;
 	}
-	return NEED_MORE;
+
+	if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
+												 this->ike_sa, FALSE))
+	{
+		DBG1(DBG_IKE, "cancelling IKE_SA setup due to uniqueness policy");
+		charon->bus->alert(charon->bus, ALERT_UNIQUE_KEEP);
+		message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
+							chunk_empty);
+		return FAILED;
+	}
+	if (!charon->bus->authorize(charon->bus, TRUE))
+	{
+		DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
+		goto peer_auth_failed;
+	}
+	if (this->ike_sa->supports_extension(this->ike_sa, EXT_IKE_REDIRECTION) &&
+		charon->redirect->redirect_on_auth(charon->redirect, this->ike_sa,
+										   &gateway))
+	{
+		delete_ike_sa_job_t *job;
+		chunk_t data;
+
+		DBG1(DBG_IKE, "redirecting peer to %Y", gateway);
+		data = redirect_data_create(gateway, chunk_empty);
+		message->add_notify(message, FALSE, REDIRECT, data);
+		gateway->destroy(gateway);
+		chunk_free(&data);
+		/* we use this condition to prevent the CHILD_SA from getting created */
+		this->ike_sa->set_condition(this->ike_sa, COND_REDIRECTED, TRUE);
+		/* if the peer does not delete the SA we do so after a while */
+		job = delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE);
+		lib->scheduler->schedule_job(lib->scheduler, (job_t*)job,
+						lib->settings->get_int(lib->settings,
+							"%s.half_open_timeout", HALF_OPEN_IKE_SA_TIMEOUT,
+							lib->ns));
+	}
+	DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
+		 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->set_state(this->ike_sa, IKE_ESTABLISHED);
+	charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
+	return SUCCESS;
 
 peer_auth_failed:
 	message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
@@ -964,6 +993,15 @@ METHOD(task_t, process_i, status_t,
 				case ME_ENDPOINT:
 					/* handled in ike_me task */
 					break;
+				case REDIRECT:
+					DESTROY_IF(this->redirect_to);
+					this->redirect_to = redirect_data_parse(
+								notify->get_notification_data(notify), NULL);
+					if (!this->redirect_to)
+					{
+						DBG1(DBG_IKE, "received invalid REDIRECT notify");
+					}
+					break;
 				default:
 				{
 					if (type <= 16383)
@@ -1094,30 +1132,35 @@ METHOD(task_t, process_i, status_t,
 	{
 		this->expect_another_auth = FALSE;
 	}
-	if (!this->expect_another_auth && !this->do_another_auth && !this->my_auth)
+	if (this->expect_another_auth || this->do_another_auth || this->my_auth)
 	{
-		if (!update_cfg_candidates(this, TRUE))
-		{
-			goto peer_auth_failed;
-		}
-		if (!charon->bus->authorize(charon->bus, TRUE))
-		{
-			DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, "
-					      "cancelling");
-			goto peer_auth_failed;
-		}
-		DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
-			 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->set_state(this->ike_sa, IKE_ESTABLISHED);
-		charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
-		return SUCCESS;
+		return NEED_MORE;
 	}
-	return NEED_MORE;
+	if (!update_cfg_candidates(this, TRUE))
+	{
+		goto peer_auth_failed;
+	}
+	if (!charon->bus->authorize(charon->bus, TRUE))
+	{
+		DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, "
+				      "cancelling");
+		goto peer_auth_failed;
+	}
+	DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
+		 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->set_state(this->ike_sa, IKE_ESTABLISHED);
+	charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
+
+	if (this->redirect_to)
+	{
+		this->ike_sa->handle_redirect(this->ike_sa, this->redirect_to);
+	}
+	return SUCCESS;
 
 peer_auth_failed:
 	charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED);
@@ -1141,6 +1184,7 @@ METHOD(task_t, migrate, void,
 	DESTROY_IF(this->peer_cfg);
 	DESTROY_IF(this->my_auth);
 	DESTROY_IF(this->other_auth);
+	DESTROY_IF(this->redirect_to);
 	this->candidates->destroy_offset(this->candidates, offsetof(peer_cfg_t, destroy));
 
 	this->my_packet = NULL;
@@ -1149,6 +1193,7 @@ METHOD(task_t, migrate, void,
 	this->peer_cfg = NULL;
 	this->my_auth = NULL;
 	this->other_auth = NULL;
+	this->redirect_to = NULL;
 	this->do_another_auth = TRUE;
 	this->expect_another_auth = TRUE;
 	this->authentication_failed = FALSE;
@@ -1165,6 +1210,7 @@ METHOD(task_t, destroy, void,
 	DESTROY_IF(this->my_auth);
 	DESTROY_IF(this->other_auth);
 	DESTROY_IF(this->peer_cfg);
+	DESTROY_IF(this->redirect_to);
 	this->candidates->destroy_offset(this->candidates, offsetof(peer_cfg_t, destroy));
 	free(this);
 }
diff --git a/src/libcharon/sa/ikev2/tasks/ike_config.c b/src/libcharon/sa/ikev2/tasks/ike_config.c
index 646f20c..6c42b81 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_config.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_config.c
@@ -333,6 +333,11 @@ METHOD(task_t, build_r, status_t,
 		linked_list_t *vips, *pools;
 		host_t *requested;
 
+		if (this->ike_sa->has_condition(this->ike_sa, COND_REDIRECTED))
+		{	/* don't assign attributes for redirected SAs */
+			return SUCCESS;
+		}
+
 		id = this->ike_sa->get_other_eap_id(this->ike_sa);
 		config = this->ike_sa->get_peer_cfg(this->ike_sa);
 		vips = linked_list_create();
diff --git a/src/libcharon/sa/ikev2/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c
index 1ff643d..78579be 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_init.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_init.c
@@ -118,6 +118,11 @@ struct private_ike_init_t {
 	 * Whether to use Signature Authentication as per RFC 7427
 	 */
 	bool signature_authentication;
+
+	/**
+	 * Whether to follow IKEv2 redirects as per RFC 5685
+	 */
+	bool follow_redirects;
 };
 
 /**
@@ -166,7 +171,7 @@ static void send_supported_hash_algorithms(private_ike_init_t *this,
 			enumerator = auth->create_enumerator(auth);
 			while (enumerator->enumerate(enumerator, &rule, &config))
 			{
-				if (rule == AUTH_RULE_SIGNATURE_SCHEME)
+				if (rule == AUTH_RULE_IKE_SIGNATURE_SCHEME)
 				{
 					hash = hasher_from_signature_scheme(config);
 					if (hasher_algorithm_for_ikev2(hash))
@@ -324,6 +329,29 @@ static bool build_payloads(private_ike_init_t *this, message_t *message)
 			send_supported_hash_algorithms(this, message);
 		}
 	}
+	/* notify other peer if we support redirection */
+	if (!this->old_sa && this->initiator && this->follow_redirects)
+	{
+		identification_t *gateway;
+		host_t *from;
+		chunk_t data;
+
+		from = this->ike_sa->get_redirected_from(this->ike_sa);
+		if (from)
+		{
+			gateway = identification_create_from_sockaddr(
+													from->get_sockaddr(from));
+			data = redirect_data_create(gateway, chunk_empty);
+			message->add_notify(message, FALSE, REDIRECTED_FROM, data);
+			chunk_free(&data);
+			gateway->destroy(gateway);
+		}
+		else
+		{
+			message->add_notify(message, FALSE, REDIRECT_SUPPORTED,
+								chunk_empty);
+		}
+	}
 	return TRUE;
 }
 
@@ -391,6 +419,30 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
 							handle_supported_hash_algorithms(this, notify);
 						}
 						break;
+					case REDIRECTED_FROM:
+					{
+						identification_t *gateway;
+						chunk_t data;
+
+						data = notify->get_notification_data(notify);
+						gateway = redirect_data_parse(data, NULL);
+						if (!gateway)
+						{
+							DBG1(DBG_IKE, "received invalid REDIRECTED_FROM "
+								 "notify, ignored");
+							break;
+						}
+						DBG1(DBG_IKE, "client got redirected from %Y", gateway);
+						gateway->destroy(gateway);
+						/* fall-through */
+					}
+					case REDIRECT_SUPPORTED:
+						if (!this->old_sa)
+						{
+							this->ike_sa->enable_extension(this->ike_sa,
+														   EXT_IKE_REDIRECTION);
+						}
+						break;
 					default:
 						/* other notifies are handled elsewhere */
 						break;
@@ -550,6 +602,8 @@ static bool derive_keys(private_ike_init_t *this,
 METHOD(task_t, build_r, status_t,
 	private_ike_init_t *this, message_t *message)
 {
+	identification_t *gateway;
+
 	/* check if we have everything we need */
 	if (this->proposal == NULL ||
 		this->other_nonce.len == 0 || this->my_nonce.len == 0)
@@ -560,6 +614,22 @@ METHOD(task_t, build_r, status_t,
 	}
 	this->ike_sa->set_proposal(this->ike_sa, this->proposal);
 
+	/* check if we'd have to redirect the client */
+	if (!this->old_sa &&
+		this->ike_sa->supports_extension(this->ike_sa, EXT_IKE_REDIRECTION) &&
+		charon->redirect->redirect_on_init(charon->redirect, this->ike_sa,
+										   &gateway))
+	{
+		chunk_t data;
+
+		DBG1(DBG_IKE, "redirecting peer to %Y", gateway);
+		data = redirect_data_create(gateway, this->other_nonce);
+		message->add_notify(message, TRUE, REDIRECT, data);
+		gateway->destroy(gateway);
+		chunk_free(&data);
+		return FAILED;
+	}
+
 	if (this->dh == NULL ||
 		!this->proposal->has_dh_group(this->proposal, this->dh_group))
 	{
@@ -623,6 +693,54 @@ static void raise_alerts(private_ike_init_t *this, notify_type_t type)
 	}
 }
 
+METHOD(task_t, pre_process_i, status_t,
+	private_ike_init_t *this, message_t *message)
+{
+	enumerator_t *enumerator;
+	payload_t *payload;
+
+	/* check for erroneous notifies */
+	enumerator = message->create_payload_enumerator(message);
+	while (enumerator->enumerate(enumerator, &payload))
+	{
+		if (payload->get_type(payload) == PLV2_NOTIFY)
+		{
+			notify_payload_t *notify = (notify_payload_t*)payload;
+			notify_type_t type = notify->get_notify_type(notify);
+
+			switch (type)
+			{
+				case REDIRECT:
+				{
+					identification_t *gateway;
+					chunk_t data, nonce = chunk_empty;
+					status_t status = SUCCESS;
+
+					if (this->old_sa)
+					{
+						break;
+					}
+					data = notify->get_notification_data(notify);
+					gateway = redirect_data_parse(data, &nonce);
+					if (!gateway || !chunk_equals(nonce, this->my_nonce))
+					{
+						DBG1(DBG_IKE, "received invalid REDIRECT notify");
+						status = FAILED;
+					}
+					DESTROY_IF(gateway);
+					chunk_free(&nonce);
+					enumerator->destroy(enumerator);
+					return status;
+				}
+				default:
+					break;
+			}
+		}
+	}
+	enumerator->destroy(enumerator);
+	return SUCCESS;
+}
+
 METHOD(task_t, process_i, status_t,
 	private_ike_init_t *this, message_t *message)
 {
@@ -678,6 +796,29 @@ METHOD(task_t, process_i, status_t,
 					this->retry++;
 					return NEED_MORE;
 				}
+				case REDIRECT:
+				{
+					identification_t *gateway;
+					chunk_t data, nonce = chunk_empty;
+					status_t status = FAILED;
+
+					if (this->old_sa)
+					{
+						DBG1(DBG_IKE, "received REDIRECT notify during rekeying"
+						     ", ignored");
+						break;
+					}
+					data = notify->get_notification_data(notify);
+					gateway = redirect_data_parse(data, &nonce);
+					if (this->ike_sa->handle_redirect(this->ike_sa, gateway))
+					{
+						status = NEED_MORE;
+					}
+					DESTROY_IF(gateway);
+					chunk_free(&nonce);
+					enumerator->destroy(enumerator);
+					return status;
+				}
 				default:
 				{
 					if (type <= 16383)
@@ -802,6 +943,8 @@ ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa)
 		.old_sa = old_sa,
 		.signature_authentication = lib->settings->get_bool(lib->settings,
 								"%s.signature_authentication", TRUE, lib->ns),
+		.follow_redirects = lib->settings->get_bool(lib->settings,
+								"%s.follow_redirects", TRUE, lib->ns),
 	);
 	this->nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
 
@@ -809,6 +952,7 @@ ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa)
 	{
 		this->public.task.build = _build_i;
 		this->public.task.process = _process_i;
+		this->public.task.pre_process = _pre_process_i;
 	}
 	else
 	{
diff --git a/src/libcharon/sa/ikev2/tasks/ike_me.c b/src/libcharon/sa/ikev2/tasks/ike_me.c
index a7e7505..10d412f 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_me.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_me.c
@@ -17,7 +17,6 @@
 
 #include <string.h>
 
-#include <hydra.h>
 #include <daemon.h>
 #include <config/peer_cfg.h>
 #include <encoding/payloads/id_payload.h>
@@ -135,8 +134,8 @@ static void gather_and_add_endpoints(private_ike_me_t *this, message_t *message)
 	host = this->ike_sa->get_my_host(this->ike_sa);
 	port = host->get_port(host);
 
-	enumerator = hydra->kernel_interface->create_address_enumerator(
-									hydra->kernel_interface, ADDR_TYPE_REGULAR);
+	enumerator = charon->kernel->create_address_enumerator(charon->kernel,
+														   ADDR_TYPE_REGULAR);
 	while (enumerator->enumerate(enumerator, (void**)&addr))
 	{
 		host = addr->clone(addr);
diff --git a/src/libcharon/sa/ikev2/tasks/ike_mobike.c b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
index cbdc5e7..3f7bb17 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_mobike.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
@@ -18,7 +18,6 @@
 
 #include <string.h>
 
-#include <hydra.h>
 #include <daemon.h>
 #include <sa/ikev2/tasks/ike_natd.h>
 #include <encoding/payloads/notify_payload.h>
@@ -196,8 +195,8 @@ static void build_address_list(private_ike_mobike_t *this, message_t *message)
 	int added = 0;
 
 	me = this->ike_sa->get_my_host(this->ike_sa);
-	enumerator = hydra->kernel_interface->create_address_enumerator(
-									hydra->kernel_interface, ADDR_TYPE_REGULAR);
+	enumerator = charon->kernel->create_address_enumerator(charon->kernel,
+														   ADDR_TYPE_REGULAR);
 	while (enumerator->enumerate(enumerator, (void**)&host))
 	{
 		if (me->ip_equals(me, host))
@@ -333,8 +332,7 @@ METHOD(ike_mobike_t, transmit, bool,
 
 	if (!this->check)
 	{
-		me = hydra->kernel_interface->get_source_addr(hydra->kernel_interface,
-													  other_old, me_old);
+		me = charon->kernel->get_source_addr(charon->kernel, other_old, me_old);
 		if (me)
 		{
 			if (me->ip_equals(me, me_old))
@@ -372,8 +370,7 @@ METHOD(ike_mobike_t, transmit, bool,
 		{
 			continue;
 		}
-		me = hydra->kernel_interface->get_source_addr(
-										hydra->kernel_interface, other, NULL);
+		me = charon->kernel->get_source_addr(charon->kernel, other, NULL);
 		if (me)
 		{
 			/* reuse port for an active address, 4500 otherwise */
@@ -407,7 +404,7 @@ METHOD(task_t, build_i, status_t,
 
 		/* we check if the existing address is still valid */
 		old = message->get_source(message);
-		new = hydra->kernel_interface->get_source_addr(hydra->kernel_interface,
+		new = charon->kernel->get_source_addr(charon->kernel,
 										message->get_destination(message), old);
 		if (new)
 		{
diff --git a/src/libcharon/sa/ikev2/tasks/ike_natd.c b/src/libcharon/sa/ikev2/tasks/ike_natd.c
index dd34c12..4bf5264 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_natd.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_natd.c
@@ -18,7 +18,6 @@
 
 #include <string.h>
 
-#include <hydra.h>
 #include <daemon.h>
 #include <config/peer_cfg.h>
 #include <crypto/hashers/hasher.h>
@@ -86,7 +85,7 @@ static bool force_encap(ike_cfg_t *ike_cfg)
 {
 	if (!ike_cfg->force_encap(ike_cfg))
 	{
-		return hydra->kernel_interface->get_features(hydra->kernel_interface) &
+		return charon->kernel->get_features(charon->kernel) &
 					KERNEL_REQUIRE_UDP_ENCAPSULATION;
 	}
 	return TRUE;
@@ -327,7 +326,7 @@ METHOD(task_t, build_i, status_t,
 	}
 	else
 	{
-		host = hydra->kernel_interface->get_source_addr(hydra->kernel_interface,
+		host = charon->kernel->get_source_addr(charon->kernel,
 							this->ike_sa->get_other_host(this->ike_sa), NULL);
 		if (host)
 		{	/* 2. */
@@ -341,8 +340,8 @@ METHOD(task_t, build_i, status_t,
 		}
 		else
 		{	/* 3. */
-			enumerator = hydra->kernel_interface->create_address_enumerator(
-									hydra->kernel_interface, ADDR_TYPE_REGULAR);
+			enumerator = charon->kernel->create_address_enumerator(
+											charon->kernel, ADDR_TYPE_REGULAR);
 			while (enumerator->enumerate(enumerator, (void**)&host))
 			{
 				/* apply port 500 to host, but work on a copy */
diff --git a/src/libcharon/sa/ikev2/tasks/ike_redirect.c b/src/libcharon/sa/ikev2/tasks/ike_redirect.c
new file mode 100644
index 0000000..f82c80f
--- /dev/null
+++ b/src/libcharon/sa/ikev2/tasks/ike_redirect.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "ike_redirect.h"
+
+#include <daemon.h>
+#include <processing/jobs/delete_ike_sa_job.h>
+
+typedef struct private_ike_redirect_t private_ike_redirect_t;
+
+/**
+ * Private members
+ */
+struct private_ike_redirect_t {
+
+	/**
+	 * Public interface
+	 */
+	ike_redirect_t public;
+
+	/**
+	 * Assigned IKE_SA
+	 */
+	ike_sa_t *ike_sa;
+
+	/**
+	 * Gateway ID to redirect to
+	 */
+	identification_t *gateway;
+};
+
+METHOD(task_t, build_i, status_t,
+	private_ike_redirect_t *this, message_t *message)
+{
+	chunk_t data;
+
+	DBG1(DBG_IKE, "redirecting peer to %Y", this->gateway);
+	data = redirect_data_create(this->gateway, chunk_empty);
+	message->add_notify(message, FALSE, REDIRECT, data);
+	chunk_free(&data);
+	this->ike_sa->set_condition(this->ike_sa, COND_REDIRECTED, TRUE);
+	return NEED_MORE;
+}
+
+METHOD(task_t, process_r, status_t,
+	private_ike_redirect_t *this, message_t *message)
+{
+	notify_payload_t *notify;
+	identification_t *to;
+
+	notify = message->get_notify(message, REDIRECT);
+	if (!notify)
+	{
+		return SUCCESS;
+	}
+
+	to = redirect_data_parse(notify->get_notification_data(notify), NULL);
+	if (!to)
+	{
+		DBG1(DBG_IKE, "received invalid REDIRECT notify");
+	}
+	else
+	{
+		this->ike_sa->handle_redirect(this->ike_sa, to);
+		to->destroy(to);
+	}
+	return SUCCESS;
+}
+
+METHOD(task_t, build_r, status_t,
+	private_ike_redirect_t *this, message_t *message)
+{
+	/* not called because SUCCESS is returned above */
+	return SUCCESS;
+}
+
+METHOD(task_t, process_i, status_t,
+	private_ike_redirect_t *this, message_t *message)
+{
+	delete_ike_sa_job_t *job;
+
+	/* if the peer does not delete the SA we do so after a while */
+	job = delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE);
+	lib->scheduler->schedule_job(lib->scheduler, (job_t*)job,
+					lib->settings->get_int(lib->settings,
+							"%s.half_open_timeout", HALF_OPEN_IKE_SA_TIMEOUT,
+							lib->ns));
+	return SUCCESS;
+}
+
+METHOD(task_t, get_type, task_type_t,
+	private_ike_redirect_t *this)
+{
+	return TASK_IKE_REDIRECT;
+}
+
+METHOD(task_t, migrate, void,
+	private_ike_redirect_t *this, ike_sa_t *ike_sa)
+{
+	this->ike_sa = ike_sa;
+}
+
+METHOD(task_t, destroy, void,
+	private_ike_redirect_t *this)
+{
+	DESTROY_IF(this->gateway);
+	free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_redirect_t *ike_redirect_create(ike_sa_t *ike_sa, identification_t *to)
+{
+	private_ike_redirect_t *this;
+
+	INIT(this,
+		.public = {
+			.task = {
+				.get_type = _get_type,
+				.build = _build_r,
+				.process = _process_r,
+				.migrate = _migrate,
+				.destroy = _destroy,
+			},
+		},
+		.ike_sa = ike_sa,
+	);
+
+	if (to)
+	{
+		this->gateway = to->clone(to);
+		this->public.task.build = _build_i;
+		this->public.task.process = _process_i;
+	}
+
+	return &this->public;
+}
diff --git a/src/libcharon/sa/ikev2/tasks/ike_redirect.h b/src/libcharon/sa/ikev2/tasks/ike_redirect.h
new file mode 100644
index 0000000..afa00ce
--- /dev/null
+++ b/src/libcharon/sa/ikev2/tasks/ike_redirect.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+/**
+ * @defgroup ike_redirect ike_redirect
+ * @{ @ingroup tasks_v2
+ */
+
+#ifndef IKE_REDIRECT_H_
+#define IKE_REDIRECT_H_
+
+typedef struct ike_redirect_t ike_redirect_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/task.h>
+
+/**
+ * Task that handles redirection requests for established SAs.
+ */
+struct ike_redirect_t {
+
+	/**
+	 * Implements the task_t interface
+	 */
+	task_t task;
+};
+
+/**
+ * Create a new ike_redirect_t task.
+ *
+ * As initiator (i.e. original responder) pass the ID of the target gateway,
+ * as responder (i.e. original initiator) this argument is NULL.
+ *
+ * @param ike_sa		IKE_SA this task works for
+ * @param to			gateway ID (gets cloned), or NULL as responder
+ * @return				task instance
+ */
+ike_redirect_t *ike_redirect_create(ike_sa_t *ike_sa,
+									identification_t *to);
+
+#endif /** IKE_REDIRECT_H_ @}*/
diff --git a/src/libcharon/sa/ikev2/tasks/ike_vendor.c b/src/libcharon/sa/ikev2/tasks/ike_vendor.c
index cb3c270..e85b276 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_vendor.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_vendor.c
@@ -13,6 +13,29 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2016 secunet Security Networks AG
+ * Copyright (C) 2016 Thomas Egerer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 #include "ike_vendor.h"
 
 #include <daemon.h>
@@ -49,6 +72,8 @@ typedef struct {
 	char *desc;
 	/* extension flag negotiated with vendor ID, if any */
 	ike_extension_t extension;
+	/* Value from strongswan.conf, whether to send vendor ID */
+	char *setting;
 	/* length of vendor ID string, 0 for NULL terminated */
 	int len;
 	/* vendor ID string */
@@ -68,23 +93,23 @@ static chunk_t get_vid_data(vid_data_t *data)
  */
 static vid_data_t vids[] = {
 	/* strongSwan MD5("strongSwan") */
-	{ "strongSwan", EXT_STRONGSWAN, 16,
+	{ "strongSwan", EXT_STRONGSWAN, "send_vendor_id", 16,
 	  "\x88\x2f\xe5\x6d\x6f\xd2\x0d\xbc\x22\x51\x61\x3b\x2e\xbe\x5b\xeb"},
-	{ "Cisco Delete Reason", 0, 0,
+	{ "Cisco Delete Reason", 0, NULL, 0,
 	  "CISCO-DELETE-REASON" },
-	{ "Cisco Copyright (c) 2009", 0, 0,
+	{ "Cisco Copyright (c) 2009", 0, NULL, 0,
 	  "CISCO(COPYRIGHT)&Copyright (c) 2009 Cisco Systems, Inc." },
-	{ "FRAGMENTATION", 0, 16,
+	{ "FRAGMENTATION", 0, NULL, 16,
 	  "\x40\x48\xb7\xd5\x6e\xbc\xe8\x85\x25\xe7\xde\x7f\x00\xd6\xc2\xd3"},
-	{ "MS NT5 ISAKMPOAKLEY v7", 0, 20,
+	{ "MS NT5 ISAKMPOAKLEY v7", 0, NULL, 20,
 	  "\x1e\x2b\x51\x69\x05\x99\x1c\x7d\x7c\x96\xfc\xbf\xb5\x87\xe4\x61\x00\x00\x00\x07"},
-	{ "MS NT5 ISAKMPOAKLEY v8", 0, 20,
+	{ "MS NT5 ISAKMPOAKLEY v8", 0, NULL, 20,
 	  "\x1e\x2b\x51\x69\x05\x99\x1c\x7d\x7c\x96\xfc\xbf\xb5\x87\xe4\x61\x00\x00\x00\x08"},
-	{ "MS NT5 ISAKMPOAKLEY v9", 0, 20,
+	{ "MS NT5 ISAKMPOAKLEY v9", 0, NULL, 20,
 	  "\x1e\x2b\x51\x69\x05\x99\x1c\x7d\x7c\x96\xfc\xbf\xb5\x87\xe4\x61\x00\x00\x00\x09"},
-	{ "MS-Negotiation Discovery Capable", 0, 16,
+	{ "MS-Negotiation Discovery Capable", 0, NULL, 16,
 	  "\xfb\x1d\xe3\xcd\xf3\x41\xb7\xea\x16\xb7\xe5\xbe\x08\x55\xf1\x20"},
-	{ "Vid-Initial-Contact", 0, 16,
+	{ "Vid-Initial-Contact", 0, NULL, 16,
 	  "\x26\x24\x4d\x38\xed\xdb\x61\xb3\x17\x2a\x36\xe3\xd0\xcf\xb8\x19"},
 };
 
@@ -92,14 +117,19 @@ METHOD(task_t, build, status_t,
 	private_ike_vendor_t *this, message_t *message)
 {
 	vendor_id_payload_t *vid;
-	bool strongswan;
+	bool send_vid;
 	int i;
 
-	strongswan = lib->settings->get_bool(lib->settings,
-							"%s.send_vendor_id", FALSE, lib->ns);
 	for (i = 0; i < countof(vids); i++)
 	{
-		if (vids[i].extension == EXT_STRONGSWAN && strongswan)
+		send_vid = FALSE;
+
+		if (vids[i].setting)
+		{
+			send_vid = lib->settings->get_bool(lib->settings, "%s.%s", send_vid,
+											   lib->ns, vids[i].setting);
+		}
+		if (send_vid)
 		{
 			DBG2(DBG_IKE, "sending %s vendor ID", vids[i].desc);
 			vid = vendor_id_payload_create_data(PLV2_VENDOR_ID,
diff --git a/src/libcharon/sa/ikev2/tasks/ike_verify_peer_cert.c b/src/libcharon/sa/ikev2/tasks/ike_verify_peer_cert.c
new file mode 100644
index 0000000..069d51d
--- /dev/null
+++ b/src/libcharon/sa/ikev2/tasks/ike_verify_peer_cert.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "ike_verify_peer_cert.h"
+
+#include <daemon.h>
+#include <sa/ikev2/tasks/ike_delete.h>
+
+typedef struct private_ike_verify_peer_cert_t private_ike_verify_peer_cert_t;
+
+/**
+ * Private members
+ */
+struct private_ike_verify_peer_cert_t {
+
+	/**
+	 * Public methods and task_t interface.
+	 */
+	ike_verify_peer_cert_t public;
+
+	/**
+	 * Assigned IKE_SA.
+	 */
+	ike_sa_t *ike_sa;
+
+	/**
+	 * Child ike_delete task, if necessary
+	 */
+	ike_delete_t *ike_delete;
+};
+
+METHOD(task_t, build_i, status_t,
+	private_ike_verify_peer_cert_t *this, message_t *message)
+{
+	if (!this->ike_sa->verify_peer_certificate(this->ike_sa))
+	{
+		DBG1(DBG_IKE, "peer certificate verification failed, deleting SA");
+		this->ike_delete = ike_delete_create(this->ike_sa, TRUE);
+		return this->ike_delete->task.build(&this->ike_delete->task, message);
+	}
+	DBG1(DBG_IKE, "peer certificate successfully verified");
+	message->set_exchange_type(message, EXCHANGE_TYPE_UNDEFINED);
+	return SUCCESS;
+}
+
+METHOD(task_t, process_i, status_t,
+	private_ike_verify_peer_cert_t *this, message_t *message)
+{
+	if (this->ike_delete)
+	{
+		this->ike_delete->task.process(&this->ike_delete->task, message);
+		/* try to reestablish the IKE_SA and all children */
+		this->ike_sa->reestablish(this->ike_sa);
+	}
+	return DESTROY_ME;
+}
+
+METHOD(task_t, get_type, task_type_t,
+	private_ike_verify_peer_cert_t *this)
+{
+	return TASK_IKE_VERIFY_PEER_CERT;
+}
+
+METHOD(task_t, migrate, void,
+	private_ike_verify_peer_cert_t *this, ike_sa_t *ike_sa)
+{
+	if (this->ike_delete)
+	{
+		this->ike_delete->task.migrate(&this->ike_delete->task, ike_sa);
+	}
+	this->ike_sa = ike_sa;
+}
+
+METHOD(task_t, destroy, void,
+	private_ike_verify_peer_cert_t *this)
+{
+	if (this->ike_delete)
+	{
+		this->ike_delete->task.destroy(&this->ike_delete->task);
+	}
+	free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_verify_peer_cert_t *ike_verify_peer_cert_create(ike_sa_t *ike_sa)
+{
+	private_ike_verify_peer_cert_t *this;
+
+	INIT(this,
+		.public = {
+			.task = {
+				.get_type = _get_type,
+				.migrate = _migrate,
+				.build = _build_i,
+				.process = _process_i,
+				.destroy = _destroy,
+			},
+		},
+		.ike_sa = ike_sa,
+	);
+
+	return &this->public;
+}
diff --git a/src/libcharon/sa/ikev2/tasks/ike_verify_peer_cert.h b/src/libcharon/sa/ikev2/tasks/ike_verify_peer_cert.h
new file mode 100644
index 0000000..3d9aae0
--- /dev/null
+++ b/src/libcharon/sa/ikev2/tasks/ike_verify_peer_cert.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+/**
+ * @defgroup ike_verify_peer_cert ike_verify_peer_cert
+ * @{ @ingroup tasks_v2
+ */
+
+#ifndef IKE_VERIFY_PEER_CERT_H_
+#define IKE_VERIFY_PEER_CERT_H_
+
+typedef struct ike_verify_peer_cert_t ike_verify_peer_cert_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/task.h>
+
+/**
+ * Task of type ike_verify_peer_cert, verifies a peer's certificate.
+ *
+ * This task (re-)verifies the peer's certificate explicitly including online
+ * OCSP and CRL checks.
+ */
+struct ike_verify_peer_cert_t {
+
+	/**
+	 * Implements the task_t interface
+	 */
+	task_t task;
+};
+
+/**
+ * Create a new ike_verify_peer_cert task.
+ *
+ * This task is initiator only.
+ *
+ * @param ike_sa		IKE_SA this task works for
+ * @return				ike_verify_peer_cert task to handle by the task_manager
+ */
+ike_verify_peer_cert_t *ike_verify_peer_cert_create(ike_sa_t *ike_sa);
+
+#endif /** IKE_VERIFY_PEER_CERT_H_ @}*/
diff --git a/src/libcharon/sa/redirect_manager.c b/src/libcharon/sa/redirect_manager.c
new file mode 100644
index 0000000..ff92ac2
--- /dev/null
+++ b/src/libcharon/sa/redirect_manager.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "redirect_manager.h"
+
+#include <collections/linked_list.h>
+#include <threading/rwlock.h>
+#include <bio/bio_reader.h>
+#include <bio/bio_writer.h>
+
+typedef struct private_redirect_manager_t private_redirect_manager_t;
+
+/**
+ * Private data
+ */
+struct private_redirect_manager_t {
+
+	/**
+	 * Public interface
+	 */
+	redirect_manager_t public;
+
+	/**
+	 * Registered providers
+	 */
+	linked_list_t *providers;
+
+	/**
+	 * Lock to access list of providers
+	 */
+	rwlock_t *lock;
+};
+
+
+/**
+ * Gateway identify types
+ *
+ * The encoding is the same as that for corresponding ID payloads.
+ */
+typedef enum {
+	/** IPv4 address of the VPN gateway */
+	GATEWAY_ID_TYPE_IPV4 = 1,
+	/** IPv6 address of the VPN gateway */
+	GATEWAY_ID_TYPE_IPV6 = 2,
+	/** FQDN of the VPN gateway */
+	GATEWAY_ID_TYPE_FQDN = 3,
+} gateway_id_type_t;
+
+/**
+ * Mapping of gateway identity types to identity types
+ */
+static id_type_t gateway_to_id_type(gateway_id_type_t type)
+{
+	switch (type)
+	{
+		case GATEWAY_ID_TYPE_IPV4:
+			return ID_IPV4_ADDR;
+		case GATEWAY_ID_TYPE_IPV6:
+			return ID_IPV6_ADDR;
+		case GATEWAY_ID_TYPE_FQDN:
+			return ID_FQDN;
+		default:
+			return 0;
+	}
+}
+
+/**
+ * Mapping of identity types to gateway identity types
+ */
+static gateway_id_type_t id_type_to_gateway(id_type_t type)
+{
+	switch (type)
+	{
+		case ID_IPV4_ADDR:
+			return GATEWAY_ID_TYPE_IPV4;
+		case ID_IPV6_ADDR:
+			return GATEWAY_ID_TYPE_IPV6;
+		case ID_FQDN:
+			return GATEWAY_ID_TYPE_FQDN;
+		default:
+			return 0;
+	}
+}
+
+METHOD(redirect_manager_t, add_provider, void,
+	private_redirect_manager_t *this, redirect_provider_t *provider)
+{
+	this->lock->write_lock(this->lock);
+	this->providers->insert_last(this->providers, provider);
+	this->lock->unlock(this->lock);
+}
+
+METHOD(redirect_manager_t, remove_provider, void,
+	private_redirect_manager_t *this, redirect_provider_t *provider)
+{
+	this->lock->write_lock(this->lock);
+	this->providers->remove(this->providers, provider, NULL);
+	this->lock->unlock(this->lock);
+}
+
+/**
+ * Determine whether a client should be redirected using the callback with the
+ * given offset into the redirect_provider_t interface.
+ */
+static bool should_redirect(private_redirect_manager_t *this, ike_sa_t *ike_sa,
+							identification_t **gateway, size_t offset)
+{
+	enumerator_t *enumerator;
+	void *provider;
+	bool redirect = FALSE;
+
+	this->lock->read_lock(this->lock);
+	enumerator = this->providers->create_enumerator(this->providers);
+	while (enumerator->enumerate(enumerator, &provider))
+	{
+		bool (**method)(void*,ike_sa_t*,identification_t**) = provider + offset;
+		if (*method && (*method)(provider, ike_sa, gateway))
+		{
+			if (*gateway && id_type_to_gateway((*gateway)->get_type(*gateway)))
+			{
+				redirect = TRUE;
+				break;
+			}
+			else
+			{
+				DBG1(DBG_CFG, "redirect provider returned invalid gateway ID");
+				DESTROY_IF(*gateway);
+			}
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->lock->unlock(this->lock);
+	return redirect;
+}
+
+METHOD(redirect_manager_t, redirect_on_init, bool,
+	private_redirect_manager_t *this, ike_sa_t *ike_sa,
+	identification_t **gateway)
+{
+	return should_redirect(this, ike_sa, gateway,
+						   offsetof(redirect_provider_t, redirect_on_init));
+}
+
+METHOD(redirect_manager_t, redirect_on_auth, bool,
+	private_redirect_manager_t *this, ike_sa_t *ike_sa,
+	identification_t **gateway)
+{
+	return should_redirect(this, ike_sa, gateway,
+						   offsetof(redirect_provider_t, redirect_on_auth));
+}
+
+METHOD(redirect_manager_t, destroy, void,
+	private_redirect_manager_t *this)
+{
+	this->providers->destroy(this->providers);
+	this->lock->destroy(this->lock);
+	free(this);
+}
+
+/*
+ * Described in header
+ */
+redirect_manager_t *redirect_manager_create()
+{
+	private_redirect_manager_t *this;
+
+	INIT(this,
+		.public = {
+			.add_provider = _add_provider,
+			.remove_provider = _remove_provider,
+			.redirect_on_init = _redirect_on_init,
+			.redirect_on_auth = _redirect_on_auth,
+			.destroy = _destroy,
+		},
+		.providers = linked_list_create(),
+		.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+	);
+
+	return &this->public;
+}
+
+/*
+ * Encoding of a REDIRECT or REDIRECTED_FROM notify
+ *
+                         1                   2                   3
+     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    | Next Payload  |C|  RESERVED   |         Payload Length        |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |Protocol ID(=0)| SPI Size (=0) |      Notify Message Type      |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    | GW Ident Type |  GW Ident Len |                               |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               ~
+    ~                   New Responder GW Identity                   ~
+    |                                                               |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    |                                                               |
+    ~                        Nonce Data                             ~
+    |                                                               |
+    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/*
+ * Described in header
+ */
+chunk_t redirect_data_create(identification_t *gw, chunk_t nonce)
+{
+	gateway_id_type_t type;
+	bio_writer_t *writer;
+	chunk_t data;
+
+	type = id_type_to_gateway(gw->get_type(gw));
+	if (!type)
+	{
+		return chunk_empty;
+	}
+
+	writer = bio_writer_create(0);
+	writer->write_uint8(writer, type);
+	writer->write_data8(writer, gw->get_encoding(gw));
+	if (nonce.ptr)
+	{
+		writer->write_data(writer, nonce);
+	}
+
+	data = writer->extract_buf(writer);
+	writer->destroy(writer);
+	return data;
+}
+
+/*
+ * Described in header
+ */
+identification_t *redirect_data_parse(chunk_t data, chunk_t *nonce)
+{
+	bio_reader_t *reader;
+	id_type_t id_type;
+	chunk_t gateway;
+	u_int8_t type;
+
+	reader = bio_reader_create(data);
+	if (!reader->read_uint8(reader, &type) ||
+		!reader->read_data8(reader, &gateway))
+	{
+		DBG1(DBG_ENC, "invalid REDIRECT notify data");
+		reader->destroy(reader);
+		return NULL;
+	}
+	id_type = gateway_to_id_type(type);
+	if (!id_type)
+	{
+		DBG1(DBG_ENC, "invalid gateway ID type (%d) in REDIRECT notify", type);
+		reader->destroy(reader);
+		return NULL;
+	}
+	if (nonce)
+	{
+		*nonce = chunk_clone(reader->peek(reader));
+	}
+	reader->destroy(reader);
+	return identification_create_from_encoding(id_type, gateway);
+}
diff --git a/src/libcharon/sa/redirect_manager.h b/src/libcharon/sa/redirect_manager.h
new file mode 100644
index 0000000..e875326
--- /dev/null
+++ b/src/libcharon/sa/redirect_manager.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+/**
+ * @defgroup redirect_manager redirect_manager
+ * @{ @ingroup sa
+ */
+
+#ifndef REDIRECT_MANAGER_H_
+#define REDIRECT_MANAGER_H_
+
+typedef struct redirect_manager_t redirect_manager_t;
+
+#include <sa/redirect_provider.h>
+
+/**
+ * Manages redirect providers.
+ */
+struct redirect_manager_t {
+
+	/**
+	 * Add a redirect provider.
+	 *
+	 * All registered providers are queried until one of them decides to
+	 * redirect a client.
+	 *
+	 * A provider may be called concurrently for different IKE_SAs.
+	 *
+	 * @param provider	provider to register
+	 */
+	void (*add_provider)(redirect_manager_t *this,
+						 redirect_provider_t *provider);
+
+	/**
+	 * Remove a redirect provider.
+	 *
+	 * @param provider	provider to unregister
+	 */
+	void (*remove_provider)(redirect_manager_t *this,
+							redirect_provider_t *provider);
+
+	/**
+	 * Determine whether a client should be redirected upon receipt of the
+	 * IKE_SA_INIT message.
+	 *
+	 * @param ike_sa		IKE_SA for which this is called
+	 * @param gateway[out]	new IKE gateway (IP or FQDN)
+	 * @return				TRUE if client should be redirected, FALSE otherwise
+	 */
+	bool (*redirect_on_init)(redirect_manager_t *this, ike_sa_t *ike_sa,
+							 identification_t **gateway);
+
+	/**
+	 * Determine whether a client should be redirected after the IKE_AUTH has
+	 * been handled.  Should be called after the client is authenticated and
+	 * when the server authenticates itself.
+	 *
+	 * @param ike_sa		IKE_SA for which this is called
+	 * @param gateway[out]	new IKE gateway (IP or FQDN)
+	 * @return				TRUE if client should be redirected, FALSE otherwise
+	 */
+	bool (*redirect_on_auth)(redirect_manager_t *this, ike_sa_t *ike_sa,
+							 identification_t **gateway);
+
+	/**
+	 * Destroy this instance.
+	 */
+	void (*destroy)(redirect_manager_t *this);
+};
+
+/**
+ * Create a redirect manager instance.
+ *
+ * @return					manager instance
+ */
+redirect_manager_t *redirect_manager_create();
+
+/**
+ * Create notification data of a REDIRECT or REDIRECT_FROM payload using the
+ * given gateway identity and optional nonce (only used during IKE_SA_INIT).
+ *
+ * @param gw				gateway identity (IP or FQDN), gets cloned
+ * @param nonce				nonce value, or chunk_empty, gets cloned
+ * @return					notify data, chunk_empty if ID type is not supported
+ */
+chunk_t redirect_data_create(identification_t *gw, chunk_t nonce);
+
+/**
+ * Parse notification data of a REDIRECT or REDIRECTED_FROM notify payload.
+ *
+ * @param data				notification data to parse
+ * @param[out] nonce		nonce data (allocated), if any was provided
+ * @return					gateway identity, NULL if data is invalid
+ */
+identification_t *redirect_data_parse(chunk_t data, chunk_t *nonce);
+
+#endif /** REDIRECT_MANAGER_H_ @}*/
diff --git a/src/libcharon/sa/redirect_provider.h b/src/libcharon/sa/redirect_provider.h
new file mode 100644
index 0000000..ef2288f
--- /dev/null
+++ b/src/libcharon/sa/redirect_provider.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+/**
+ * @defgroup redirect_provider redirect_provider
+ * @{ @ingroup sa
+ */
+
+#ifndef REDIRECT_PROVIDER_H_
+#define REDIRECT_PROVIDER_H_
+
+typedef struct redirect_provider_t redirect_provider_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+
+/**
+ * Interface that allows implementations to decide whether a client is
+ * redirected during IKE_SA_INIT or IKE_AUTH using RFC 5685.
+ */
+struct redirect_provider_t {
+
+	/**
+	 * Decide whether a client is redirect directly upon receipt of the
+	 * IKE_SA_INIT message.
+	 *
+	 * @param ike_sa		IKE_SA for which this is called
+	 * @param gateway[out]	new IKE gateway (IP or FQDN)
+	 * @return				TRUE if client should be redirected, FALSE otherwise
+	 */
+	bool (*redirect_on_init)(redirect_provider_t *this, ike_sa_t *ike_sa,
+							 identification_t **gateway);
+
+	/**
+	 * Decide whether a client is redirect after the IKE_AUTH has been
+	 * handled.  This is called after the client is authenticated and when the
+	 * server authenticates itself.
+	 *
+	 * @param ike_sa		IKE_SA for which this is called
+	 * @param gateway[out]	new IKE gateway (IP or FQDN)
+	 * @return				TRUE if client should be redirected, FALSE otherwise
+	 */
+	bool (*redirect_on_auth)(redirect_provider_t *this, ike_sa_t *ike_sa,
+							 identification_t **gateway);
+};
+
+#endif /** REDIRECT_PROVIDER_H_ @}*/
diff --git a/src/libcharon/sa/shunt_manager.c b/src/libcharon/sa/shunt_manager.c
index 5231994..0e9cf6e 100644
--- a/src/libcharon/sa/shunt_manager.c
+++ b/src/libcharon/sa/shunt_manager.c
@@ -16,7 +16,6 @@
 
 #include "shunt_manager.h"
 
-#include <hydra.h>
 #include <daemon.h>
 #include <threading/rwlock.h>
 #include <threading/rwlock_condvar.h>
@@ -111,22 +110,22 @@ static bool install_shunt_policy(child_cfg_t *child)
 				continue;
 			}
 			/* install out policy */
-			status |= hydra->kernel_interface->add_policy(
-								hydra->kernel_interface, host_any, host_any,
+			status |= charon->kernel->add_policy(charon->kernel,
+								host_any, host_any,
 								my_ts, other_ts, POLICY_OUT, policy_type,
 								&sa, child->get_mark(child, FALSE),
 								policy_prio);
 
 			/* install in policy */
-			status |= hydra->kernel_interface->add_policy(
-								hydra->kernel_interface, host_any, host_any,
+			status |= charon->kernel->add_policy(charon->kernel,
+								host_any, host_any,
 								other_ts, my_ts, POLICY_IN, policy_type,
 								&sa, child->get_mark(child, TRUE),
 								policy_prio);
 
 			/* install forward policy */
-			status |= hydra->kernel_interface->add_policy(
-								hydra->kernel_interface, host_any, host_any,
+			status |= charon->kernel->add_policy(charon->kernel,
+								host_any, host_any,
 								other_ts, my_ts, POLICY_FWD, policy_type,
 								&sa, child->get_mark(child, TRUE),
 								policy_prio);
@@ -248,22 +247,22 @@ static void uninstall_shunt_policy(child_cfg_t *child)
 				continue;
 			}
 			/* uninstall out policy */
-			status |= hydra->kernel_interface->del_policy(
-							hydra->kernel_interface, host_any, host_any,
+			status |= charon->kernel->del_policy(charon->kernel,
+							host_any, host_any,
 							my_ts, other_ts, POLICY_OUT, policy_type,
 							&sa, child->get_mark(child, FALSE),
 							policy_prio);
 
 			/* uninstall in policy */
-			status |= hydra->kernel_interface->del_policy(
-							hydra->kernel_interface, host_any, host_any,
+			status |= charon->kernel->del_policy(charon->kernel,
+							host_any, host_any,
 							other_ts, my_ts, POLICY_IN, policy_type,
 							&sa, child->get_mark(child, TRUE),
 							policy_prio);
 
 			/* uninstall forward policy */
-			status |= hydra->kernel_interface->del_policy(
-							hydra->kernel_interface, host_any, host_any,
+			status |= charon->kernel->del_policy(charon->kernel,
+							host_any, host_any,
 							other_ts, my_ts, POLICY_FWD, policy_type,
 							&sa, child->get_mark(child, TRUE),
 							policy_prio);
diff --git a/src/libcharon/sa/task.c b/src/libcharon/sa/task.c
index b35b581..405eda6 100644
--- a/src/libcharon/sa/task.c
+++ b/src/libcharon/sa/task.c
@@ -28,6 +28,8 @@ ENUM(task_type_names, TASK_IKE_INIT, TASK_ISAKMP_CERT_POST,
 	"IKE_REKEY",
 	"IKE_REAUTH",
 	"IKE_REAUTH_COMPLETE",
+	"IKE_REDIRECT",
+	"IKE_VERIFY_PEER_CERT",
 	"IKE_DELETE",
 	"IKE_DPD",
 	"IKE_VENDOR",
diff --git a/src/libcharon/sa/task.h b/src/libcharon/sa/task.h
index 7bd3da1..31d70fb 100644
--- a/src/libcharon/sa/task.h
+++ b/src/libcharon/sa/task.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2007-2015 Tobias Brunner
  * Copyright (C) 2006 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -57,6 +57,10 @@ enum task_type_t {
 	TASK_IKE_REAUTH,
 	/** completion task for make-before-break IKE_SA re-authentication */
 	TASK_IKE_REAUTH_COMPLETE,
+	/** redirect an active IKE_SA */
+	TASK_IKE_REDIRECT,
+	/** verify a peer's certificate */
+	TASK_IKE_VERIFY_PEER_CERT,
 	/** delete an IKE_SA */
 	TASK_IKE_DELETE,
 	/** liveness check */
@@ -154,6 +158,18 @@ struct task_t {
 	status_t (*process) (task_t *this, message_t *message);
 
 	/**
+	 * Verify a message before processing it (optional to implement by tasks).
+	 *
+	 * @param message		message to verify
+	 * @return
+	 *						- FAILED if verification is not successful, the
+	 *						  message will be silently discarded
+	 *						- DESTROY_ME if IKE_SA has to be destroyed
+	 *						- SUCCESS if verification is successful
+	 */
+	status_t (*pre_process) (task_t *this, message_t *message);
+
+	/**
 	 * Get the type of the task implementation.
 	 */
 	task_type_t (*get_type) (task_t *this);
diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c
index 90ad7e4..85e2207 100644
--- a/src/libcharon/sa/trap_manager.c
+++ b/src/libcharon/sa/trap_manager.c
@@ -16,7 +16,6 @@
 
 #include "trap_manager.h"
 
-#include <hydra.h>
 #include <daemon.h>
 #include <threading/mutex.h>
 #include <threading/rwlock.h>
@@ -195,8 +194,7 @@ METHOD(trap_manager_t, install, u_int32_t,
 		if (!me || me->is_anyaddr(me))
 		{
 			DESTROY_IF(me);
-			me = hydra->kernel_interface->get_source_addr(
-										hydra->kernel_interface, other, NULL);
+			me = charon->kernel->get_source_addr(charon->kernel, other, NULL);
 			if (!me)
 			{
 				DBG1(DBG_CFG, "installing trap failed, local address unknown");
diff --git a/src/libcharon/tests/Makefile.am b/src/libcharon/tests/Makefile.am
index 5fd8ca2..0589269 100644
--- a/src/libcharon/tests/Makefile.am
+++ b/src/libcharon/tests/Makefile.am
@@ -10,7 +10,6 @@ libcharon_tests_SOURCES = \
 
 libcharon_tests_CFLAGS = \
   -I$(top_srcdir)/src/libcharon \
-  -I$(top_srcdir)/src/libhydra \
   -I$(top_srcdir)/src/libstrongswan \
   -I$(top_srcdir)/src/libstrongswan/tests \
   -DPLUGINDIR=\""$(abs_top_builddir)/src/libstrongswan/plugins\"" \
@@ -20,6 +19,5 @@ libcharon_tests_CFLAGS = \
 libcharon_tests_LDFLAGS = @COVERAGE_LDFLAGS@
 libcharon_tests_LDADD = \
   $(top_builddir)/src/libcharon/libcharon.la \
-  $(top_builddir)/src/libhydra/libhydra.la \
   $(top_builddir)/src/libstrongswan/libstrongswan.la \
   $(top_builddir)/src/libstrongswan/tests/libtest.la
diff --git a/src/libcharon/tests/Makefile.in b/src/libcharon/tests/Makefile.in
index 910aad9..87dea16 100644
--- a/src/libcharon/tests/Makefile.in
+++ b/src/libcharon/tests/Makefile.in
@@ -109,7 +109,6 @@ am_libcharon_tests_OBJECTS =  \
 libcharon_tests_OBJECTS = $(am_libcharon_tests_OBJECTS)
 libcharon_tests_DEPENDENCIES =  \
 	$(top_builddir)/src/libcharon/libcharon.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
 	$(top_builddir)/src/libstrongswan/tests/libtest.la
 AM_V_lt = $(am__v_lt_ at AM_V@)
@@ -415,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -436,7 +437,6 @@ libcharon_tests_SOURCES = \
 
 libcharon_tests_CFLAGS = \
   -I$(top_srcdir)/src/libcharon \
-  -I$(top_srcdir)/src/libhydra \
   -I$(top_srcdir)/src/libstrongswan \
   -I$(top_srcdir)/src/libstrongswan/tests \
   -DPLUGINDIR=\""$(abs_top_builddir)/src/libstrongswan/plugins\"" \
@@ -446,7 +446,6 @@ libcharon_tests_CFLAGS = \
 libcharon_tests_LDFLAGS = @COVERAGE_LDFLAGS@
 libcharon_tests_LDADD = \
   $(top_builddir)/src/libcharon/libcharon.la \
-  $(top_builddir)/src/libhydra/libhydra.la \
   $(top_builddir)/src/libstrongswan/libstrongswan.la \
   $(top_builddir)/src/libstrongswan/tests/libtest.la
 
diff --git a/src/libcharon/tests/libcharon_tests.c b/src/libcharon/tests/libcharon_tests.c
index ec96de7..4692c30 100644
--- a/src/libcharon/tests/libcharon_tests.c
+++ b/src/libcharon/tests/libcharon_tests.c
@@ -14,7 +14,6 @@
  */
 
 #include <test_runner.h>
-#include <hydra.h>
 #include <daemon.h>
 
 /* declare test suite constructors */
@@ -39,7 +38,6 @@ static bool test_runner_init(bool init)
 	{
 		char *plugins, *plugindir;
 
-		libhydra_init();
 		libcharon_init();
 
 		plugins = getenv("TESTS_PLUGINS") ?:
@@ -59,7 +57,6 @@ static bool test_runner_init(bool init)
 		lib->processor->cancel(lib->processor);
 		lib->plugins->unload(lib->plugins);
 		libcharon_deinit();
-		libhydra_deinit();
 	}
 	return TRUE;
 }
diff --git a/src/libfast/Makefile.in b/src/libfast/Makefile.in
index 6a3a4eb..0c69254 100644
--- a/src/libfast/Makefile.in
+++ b/src/libfast/Makefile.in
@@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libhydra/Android.mk b/src/libhydra/Android.mk
deleted file mode 100644
index 7b62e95..0000000
--- a/src/libhydra/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# copy-n-paste from Makefile.am
-libhydra_la_SOURCES := \
-hydra.c hydra.h \
-kernel/kernel_interface.c kernel/kernel_interface.h \
-kernel/kernel_ipsec.c kernel/kernel_ipsec.h \
-kernel/kernel_net.c kernel/kernel_net.h \
-kernel/kernel_listener.h
-
-LOCAL_SRC_FILES := $(filter %.c,$(libhydra_la_SOURCES))
-
-# adding the plugin source files
-
-LOCAL_SRC_FILES += $(call add_plugin, kernel-pfkey)
-
-LOCAL_SRC_FILES += $(call add_plugin, kernel-netlink)
-
-# build libhydra ---------------------------------------------------------------
-
-LOCAL_C_INCLUDES += \
-	$(strongswan_PATH)/src/libstrongswan
-
-LOCAL_CFLAGS := $(strongswan_CFLAGS)
-
-LOCAL_MODULE := libhydra
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_ARM_MODE := arm
-
-LOCAL_PRELINK_MODULE := false
-
-LOCAL_SHARED_LIBRARIES += libstrongswan
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/src/libhydra/Makefile.am b/src/libhydra/Makefile.am
deleted file mode 100644
index 9cdbc01..0000000
--- a/src/libhydra/Makefile.am
+++ /dev/null
@@ -1,60 +0,0 @@
-ipseclib_LTLIBRARIES = libhydra.la
-
-libhydra_la_SOURCES = \
-hydra.c hydra.h \
-kernel/kernel_interface.c kernel/kernel_interface.h \
-kernel/kernel_ipsec.c kernel/kernel_ipsec.h \
-kernel/kernel_net.c kernel/kernel_net.h \
-kernel/kernel_listener.h
-
-libhydra_la_LIBADD = \
-  $(top_builddir)/src/libstrongswan/libstrongswan.la
-
-if USE_WINDOWS
-  libhydra_la_LIBADD += -lws2_32
-endif
-
-AM_CPPFLAGS = \
-	-I$(top_srcdir)/src/libstrongswan \
-	-DIPSEC_DIR=\"${ipsecdir}\" \
-	-DPLUGINDIR=\"${plugindir}\"
-
-AM_LDFLAGS = \
-  -no-undefined
-
-EXTRA_DIST = Android.mk
-
-# build optional plugins
-########################
-
-if MONOLITHIC
-SUBDIRS =
-else
-SUBDIRS = .
-endif
-
-if USE_KERNEL_PFKEY
-  SUBDIRS += plugins/kernel_pfkey
-if MONOLITHIC
-  libhydra_la_LIBADD += plugins/kernel_pfkey/libstrongswan-kernel-pfkey.la
-endif
-endif
-
-if USE_KERNEL_PFROUTE
-  SUBDIRS += plugins/kernel_pfroute
-if MONOLITHIC
-  libhydra_la_LIBADD += plugins/kernel_pfroute/libstrongswan-kernel-pfroute.la
-endif
-endif
-
-if USE_KERNEL_NETLINK
-  SUBDIRS += plugins/kernel_netlink
-if MONOLITHIC
-  libhydra_la_LIBADD += plugins/kernel_netlink/libstrongswan-kernel-netlink.la
-endif
-endif
-
-if MONOLITHIC
-  SUBDIRS += .
-endif
-SUBDIRS += tests
diff --git a/src/libhydra/Makefile.in b/src/libhydra/Makefile.in
deleted file mode 100644
index 9bb2e83..0000000
--- a/src/libhydra/Makefile.in
+++ /dev/null
@@ -1,922 +0,0 @@
-# Makefile.in generated by automake 1.14.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 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.
-
- at SET_MAKE@
-
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
-  case $${target_option-} in \
-      ?) ;; \
-      *) echo "am__make_running_with_option: internal error: invalid" \
-              "target option '$${target_option-}' specified" >&2; \
-         exit 1;; \
-  esac; \
-  has_opt=no; \
-  sane_makeflags=$$MAKEFLAGS; \
-  if $(am__is_gnu_make); then \
-    sane_makeflags=$$MFLAGS; \
-  else \
-    case $$MAKEFLAGS in \
-      *\\[\ \	]*) \
-        bs=\\; \
-        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
-          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
-    esac; \
-  fi; \
-  skip_next=no; \
-  strip_trailopt () \
-  { \
-    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
-  }; \
-  for flg in $$sane_makeflags; do \
-    test $$skip_next = yes && { skip_next=no; continue; }; \
-    case $$flg in \
-      *=*|--*) continue;; \
-        -*I) strip_trailopt 'I'; skip_next=yes;; \
-      -*I?*) strip_trailopt 'I';; \
-        -*O) strip_trailopt 'O'; skip_next=yes;; \
-      -*O?*) strip_trailopt 'O';; \
-        -*l) strip_trailopt 'l'; skip_next=yes;; \
-      -*l?*) strip_trailopt 'l';; \
-      -[dEDm]) skip_next=yes;; \
-      -[JT]) skip_next=yes;; \
-    esac; \
-    case $$flg in \
-      *$$target_option*) has_opt=yes; break;; \
-    esac; \
-  done; \
-  test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@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@
- at USE_WINDOWS_TRUE@am__append_1 = -lws2_32
- at USE_KERNEL_PFKEY_TRUE@am__append_2 = plugins/kernel_pfkey
- at MONOLITHIC_TRUE@@USE_KERNEL_PFKEY_TRUE at am__append_3 = plugins/kernel_pfkey/libstrongswan-kernel-pfkey.la
- at USE_KERNEL_PFROUTE_TRUE@am__append_4 = plugins/kernel_pfroute
- at MONOLITHIC_TRUE@@USE_KERNEL_PFROUTE_TRUE at am__append_5 = plugins/kernel_pfroute/libstrongswan-kernel-pfroute.la
- at USE_KERNEL_NETLINK_TRUE@am__append_6 = plugins/kernel_netlink
- at MONOLITHIC_TRUE@@USE_KERNEL_NETLINK_TRUE at am__append_7 = plugins/kernel_netlink/libstrongswan-kernel-netlink.la
-subdir = src/libhydra
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
-	$(top_srcdir)/depcomp
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
-	$(top_srcdir)/m4/config/ltoptions.m4 \
-	$(top_srcdir)/m4/config/ltsugar.m4 \
-	$(top_srcdir)/m4/config/ltversion.m4 \
-	$(top_srcdir)/m4/config/lt~obsolete.m4 \
-	$(top_srcdir)/m4/macros/split-package-version.m4 \
-	$(top_srcdir)/m4/macros/with.m4 \
-	$(top_srcdir)/m4/macros/enable-disable.m4 \
-	$(top_srcdir)/m4/macros/add-plugin.m4 \
-	$(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-	$(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_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 = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
-  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
-  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
-  for p in $$list; do echo "$$p $$p"; done | \
-  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
-  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
-    if (++n[$$2] == $(am__install_max)) \
-      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
-    END { for (dir in files) print dir, files[dir] }'
-am__base_list = \
-  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
-  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__uninstall_files_from_dir = { \
-  test -z "$$files" \
-    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
-    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
-         $(am__cd) "$$dir" && rm -f $$files; }; \
-  }
-am__installdirs = "$(DESTDIR)$(ipseclibdir)"
-LTLIBRARIES = $(ipseclib_LTLIBRARIES)
-am__DEPENDENCIES_1 =
-libhydra_la_DEPENDENCIES =  \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(am__DEPENDENCIES_1) $(am__append_3) $(am__append_5) \
-	$(am__append_7)
-am__dirstamp = $(am__leading_dot)dirstamp
-am_libhydra_la_OBJECTS = hydra.lo kernel/kernel_interface.lo \
-	kernel/kernel_ipsec.lo kernel/kernel_net.lo
-libhydra_la_OBJECTS = $(am_libhydra_la_OBJECTS)
-AM_V_lt = $(am__v_lt_ at AM_V@)
-am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 = 
-AM_V_P = $(am__v_P_ at AM_V@)
-am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_ at AM_V@)
-am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 = 
-AM_V_at = $(am__v_at_ at AM_V@)
-am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 = 
-DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-	$(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_ at AM_V@)
-am__v_CC_ = $(am__v_CC_ at AM_DEFAULT_V@)
-am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 = 
-CCLD = $(CC)
-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-	$(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_ at AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_ at AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo "  CCLD    " $@;
-am__v_CCLD_1 = 
-SOURCES = $(libhydra_la_SOURCES)
-DIST_SOURCES = $(libhydra_la_SOURCES)
-RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
-	ctags-recursive dvi-recursive html-recursive info-recursive \
-	install-data-recursive install-dvi-recursive \
-	install-exec-recursive install-html-recursive \
-	install-info-recursive install-pdf-recursive \
-	install-ps-recursive install-recursive installcheck-recursive \
-	installdirs-recursive pdf-recursive ps-recursive \
-	tags-recursive uninstall-recursive
-am__can_run_installinfo = \
-  case $$AM_UPDATE_INFO_DIR in \
-    n|no|NO) false;; \
-    *) (install-info --version) >/dev/null 2>&1;; \
-  esac
-RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
-  distclean-recursive maintainer-clean-recursive
-am__recursive_targets = \
-  $(RECURSIVE_TARGETS) \
-  $(RECURSIVE_CLEAN_TARGETS) \
-  $(am__extra_recursive_targets)
-AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
-	distdir
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates.  Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
-  BEGIN { nonempty = 0; } \
-  { items[$$0] = 1; nonempty = 1; } \
-  END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique.  This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
-  list='$(am__tagged_files)'; \
-  unique=`for i in $$list; do \
-    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-  done | $(am__uniquify_input)`
-ETAGS = etags
-CTAGS = ctags
-DIST_SUBDIRS = . plugins/kernel_pfkey plugins/kernel_pfroute \
-	plugins/kernel_netlink tests
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-am__relativize = \
-  dir0=`pwd`; \
-  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
-  sed_rest='s,^[^/]*/*,,'; \
-  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
-  sed_butlast='s,/*[^/]*$$,,'; \
-  while test -n "$$dir1"; do \
-    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
-    if test "$$first" != "."; then \
-      if test "$$first" = ".."; then \
-        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
-        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
-      else \
-        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
-        if test "$$first2" = "$$first"; then \
-          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
-        else \
-          dir2="../$$dir2"; \
-        fi; \
-        dir0="$$dir0"/"$$first"; \
-      fi; \
-    fi; \
-    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
-  done; \
-  reldir="$$dir2"
-ACLOCAL = @ACLOCAL@
-ALLOCA = @ALLOCA@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BFDLIB = @BFDLIB@
-BTLIB = @BTLIB@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
-COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLIB = @DLLIB@
-DLLTOOL = @DLLTOOL@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-EASY_INSTALL = @EASY_INSTALL@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FGREP = @FGREP@
-GEM = @GEM@
-GENHTML = @GENHTML@
-GPERF = @GPERF@
-GPRBUILD = @GPRBUILD@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LCOV = @LCOV@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LEX = @LEX@
-LEXLIB = @LEXLIB@
-LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-MYSQLCFLAG = @MYSQLCFLAG@
-MYSQLCONFIG = @MYSQLCONFIG@
-MYSQLLIB = @MYSQLLIB@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OPENSSL_LIB = @OPENSSL_LIB@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
-PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
-PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
-PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PERL = @PERL@
-PKG_CONFIG = @PKG_CONFIG@
-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
-PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
-PTHREADLIB = @PTHREADLIB@
-PYTHON = @PYTHON@
-PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
-PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
-PYTHON_PLATFORM = @PYTHON_PLATFORM@
-PYTHON_PREFIX = @PYTHON_PREFIX@
-PYTHON_VERSION = @PYTHON_VERSION@
-PY_TEST = @PY_TEST@
-RANLIB = @RANLIB@
-RTLIB = @RTLIB@
-RUBY = @RUBY@
-RUBYGEMDIR = @RUBYGEMDIR@
-RUBYINCLUDE = @RUBYINCLUDE@
-RUBYLIB = @RUBYLIB@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-SOCKLIB = @SOCKLIB@
-STRIP = @STRIP@
-UNWINDLIB = @UNWINDLIB@
-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_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-aikgen_plugins = @aikgen_plugins@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-attest_plugins = @attest_plugins@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-c_plugins = @c_plugins@
-charon_natt_port = @charon_natt_port@
-charon_plugins = @charon_plugins@
-charon_udp_port = @charon_udp_port@
-clearsilver_LIBS = @clearsilver_LIBS@
-cmd_plugins = @cmd_plugins@
-datadir = @datadir@
-datarootdir = @datarootdir@
-dbusservicedir = @dbusservicedir@
-dev_headers = @dev_headers@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-fips_mode = @fips_mode@
-gtk_CFLAGS = @gtk_CFLAGS@
-gtk_LIBS = @gtk_LIBS@
-h_plugins = @h_plugins@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-imcvdir = @imcvdir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-ipsec_script = @ipsec_script@
-ipsec_script_upper = @ipsec_script_upper@
-ipsecdir = @ipsecdir@
-ipsecgroup = @ipsecgroup@
-ipseclibdir = @ipseclibdir@
-ipsecuser = @ipsecuser@
-json_CFLAGS = @json_CFLAGS@
-json_LIBS = @json_LIBS@
-libdir = @libdir@
-libexecdir = @libexecdir@
-libiptc_CFLAGS = @libiptc_CFLAGS@
-libiptc_LIBS = @libiptc_LIBS@
-linux_headers = @linux_headers@
-localedir = @localedir@
-localstatedir = @localstatedir@
-maemo_CFLAGS = @maemo_CFLAGS@
-maemo_LIBS = @maemo_LIBS@
-manager_plugins = @manager_plugins@
-mandir = @mandir@
-medsrv_plugins = @medsrv_plugins@
-mkdir_p = @mkdir_p@
-nm_CFLAGS = @nm_CFLAGS@
-nm_LIBS = @nm_LIBS@
-nm_ca_dir = @nm_ca_dir@
-nm_plugins = @nm_plugins@
-oldincludedir = @oldincludedir@
-pcsclite_CFLAGS = @pcsclite_CFLAGS@
-pcsclite_LIBS = @pcsclite_LIBS@
-pdfdir = @pdfdir@
-piddir = @piddir@
-pkgpyexecdir = @pkgpyexecdir@
-pkgpythondir = @pkgpythondir@
-pki_plugins = @pki_plugins@
-plugindir = @plugindir@
-pool_plugins = @pool_plugins@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-pyexecdir = @pyexecdir@
-pythondir = @pythondir@
-random_device = @random_device@
-resolv_conf = @resolv_conf@
-routing_table = @routing_table@
-routing_table_prio = @routing_table_prio@
-s_plugins = @s_plugins@
-sbindir = @sbindir@
-scepclient_plugins = @scepclient_plugins@
-scripts_plugins = @scripts_plugins@
-sharedstatedir = @sharedstatedir@
-soup_CFLAGS = @soup_CFLAGS@
-soup_LIBS = @soup_LIBS@
-srcdir = @srcdir@
-starter_plugins = @starter_plugins@
-strongswan_conf = @strongswan_conf@
-strongswan_options = @strongswan_options@
-swanctldir = @swanctldir@
-sysconfdir = @sysconfdir@
-systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
-systemd_daemon_LIBS = @systemd_daemon_LIBS@
-systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
-systemd_journal_LIBS = @systemd_journal_LIBS@
-systemdsystemunitdir = @systemdsystemunitdir@
-t_plugins = @t_plugins@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-urandom_device = @urandom_device@
-xml_CFLAGS = @xml_CFLAGS@
-xml_LIBS = @xml_LIBS@
-ipseclib_LTLIBRARIES = libhydra.la
-libhydra_la_SOURCES = \
-hydra.c hydra.h \
-kernel/kernel_interface.c kernel/kernel_interface.h \
-kernel/kernel_ipsec.c kernel/kernel_ipsec.h \
-kernel/kernel_net.c kernel/kernel_net.h \
-kernel/kernel_listener.h
-
-libhydra_la_LIBADD =  \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(am__append_1) $(am__append_3) $(am__append_5) \
-	$(am__append_7)
-AM_CPPFLAGS = \
-	-I$(top_srcdir)/src/libstrongswan \
-	-DIPSEC_DIR=\"${ipsecdir}\" \
-	-DPLUGINDIR=\"${plugindir}\"
-
-AM_LDFLAGS = \
-  -no-undefined
-
-EXTRA_DIST = Android.mk
- at MONOLITHIC_FALSE@SUBDIRS = . $(am__append_2) $(am__append_4) \
- at MONOLITHIC_FALSE@	$(am__append_6) tests
-
-# build optional plugins
-########################
- at MONOLITHIC_TRUE@SUBDIRS = $(am__append_2) $(am__append_4) \
- at MONOLITHIC_TRUE@	$(am__append_6) . tests
-all: all-recursive
-
-.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 ) \
-	        && { if test -f $@; then exit 0; else break; fi; }; \
-	      exit 1;; \
-	  esac; \
-	done; \
-	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libhydra/Makefile'; \
-	$(am__cd) $(top_srcdir) && \
-	  $(AUTOMAKE) --gnu src/libhydra/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
-$(am__aclocal_m4_deps):
-
-install-ipseclibLTLIBRARIES: $(ipseclib_LTLIBRARIES)
-	@$(NORMAL_INSTALL)
-	@list='$(ipseclib_LTLIBRARIES)'; test -n "$(ipseclibdir)" || list=; \
-	list2=; for p in $$list; do \
-	  if test -f $$p; then \
-	    list2="$$list2 $$p"; \
-	  else :; fi; \
-	done; \
-	test -z "$$list2" || { \
-	  echo " $(MKDIR_P) '$(DESTDIR)$(ipseclibdir)'"; \
-	  $(MKDIR_P) "$(DESTDIR)$(ipseclibdir)" || exit 1; \
-	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(ipseclibdir)'"; \
-	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(ipseclibdir)"; \
-	}
-
-uninstall-ipseclibLTLIBRARIES:
-	@$(NORMAL_UNINSTALL)
-	@list='$(ipseclib_LTLIBRARIES)'; test -n "$(ipseclibdir)" || list=; \
-	for p in $$list; do \
-	  $(am__strip_dir) \
-	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(ipseclibdir)/$$f'"; \
-	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(ipseclibdir)/$$f"; \
-	done
-
-clean-ipseclibLTLIBRARIES:
-	-test -z "$(ipseclib_LTLIBRARIES)" || rm -f $(ipseclib_LTLIBRARIES)
-	@list='$(ipseclib_LTLIBRARIES)'; \
-	locs=`for p in $$list; do echo $$p; done | \
-	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
-	      sort -u`; \
-	test -z "$$locs" || { \
-	  echo rm -f $${locs}; \
-	  rm -f $${locs}; \
-	}
-kernel/$(am__dirstamp):
-	@$(MKDIR_P) kernel
-	@: > kernel/$(am__dirstamp)
-kernel/$(DEPDIR)/$(am__dirstamp):
-	@$(MKDIR_P) kernel/$(DEPDIR)
-	@: > kernel/$(DEPDIR)/$(am__dirstamp)
-kernel/kernel_interface.lo: kernel/$(am__dirstamp) \
-	kernel/$(DEPDIR)/$(am__dirstamp)
-kernel/kernel_ipsec.lo: kernel/$(am__dirstamp) \
-	kernel/$(DEPDIR)/$(am__dirstamp)
-kernel/kernel_net.lo: kernel/$(am__dirstamp) \
-	kernel/$(DEPDIR)/$(am__dirstamp)
-
-libhydra.la: $(libhydra_la_OBJECTS) $(libhydra_la_DEPENDENCIES) $(EXTRA_libhydra_la_DEPENDENCIES) 
-	$(AM_V_CCLD)$(LINK) -rpath $(ipseclibdir) $(libhydra_la_OBJECTS) $(libhydra_la_LIBADD) $(LIBS)
-
-mostlyclean-compile:
-	-rm -f *.$(OBJEXT)
-	-rm -f kernel/*.$(OBJEXT)
-	-rm -f kernel/*.lo
-
-distclean-compile:
-	-rm -f *.tab.c
-
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/hydra.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at kernel/$(DEPDIR)/kernel_interface.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at kernel/$(DEPDIR)/kernel_ipsec.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at kernel/$(DEPDIR)/kernel_net.Plo at am__quote@
-
-.c.o:
- at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
- at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
- at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ $<
-
-.c.obj:
- at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
- at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
- at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-
-.c.lo:
- at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
- at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
- at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LTCOMPILE) -c -o $@ $<
-
-mostlyclean-libtool:
-	-rm -f *.lo
-
-clean-libtool:
-	-rm -rf .libs _libs
-	-rm -rf kernel/.libs kernel/_libs
-
-# This directory's subdirectories are mostly independent; you can cd
-# into them and run 'make' without going through this Makefile.
-# To change the values of 'make' variables: instead of editing Makefiles,
-# (1) if the variable is set in 'config.status', edit 'config.status'
-#     (which will cause the Makefiles to be regenerated when you run 'make');
-# (2) otherwise, pass the desired values on the 'make' command line.
-$(am__recursive_targets):
-	@fail=; \
-	if $(am__make_keepgoing); then \
-	  failcom='fail=yes'; \
-	else \
-	  failcom='exit 1'; \
-	fi; \
-	dot_seen=no; \
-	target=`echo $@ | sed s/-recursive//`; \
-	case "$@" in \
-	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
-	  *) list='$(SUBDIRS)' ;; \
-	esac; \
-	for subdir in $$list; do \
-	  echo "Making $$target in $$subdir"; \
-	  if test "$$subdir" = "."; then \
-	    dot_seen=yes; \
-	    local_target="$$target-am"; \
-	  else \
-	    local_target="$$target"; \
-	  fi; \
-	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
-	  || eval $$failcom; \
-	done; \
-	if test "$$dot_seen" = "no"; then \
-	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
-	fi; test -z "$$fail"
-
-ID: $(am__tagged_files)
-	$(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-recursive
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-	set x; \
-	here=`pwd`; \
-	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
-	  include_option=--etags-include; \
-	  empty_fix=.; \
-	else \
-	  include_option=--include; \
-	  empty_fix=; \
-	fi; \
-	list='$(SUBDIRS)'; for subdir in $$list; do \
-	  if test "$$subdir" = .; then :; else \
-	    test ! -f $$subdir/TAGS || \
-	      set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
-	  fi; \
-	done; \
-	$(am__define_uniq_tagged_files); \
-	shift; \
-	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-	  test -n "$$unique" || unique=$$empty_fix; \
-	  if test $$# -gt 0; then \
-	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-	      "$$@" $$unique; \
-	  else \
-	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-	      $$unique; \
-	  fi; \
-	fi
-ctags: ctags-recursive
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-	$(am__define_uniq_tagged_files); \
-	test -z "$(CTAGS_ARGS)$$unique" \
-	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-	     $$unique
-
-GTAGS:
-	here=`$(am__cd) $(top_builddir) && pwd` \
-	  && $(am__cd) $(top_srcdir) \
-	  && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-recursive
-
-cscopelist-am: $(am__tagged_files)
-	list='$(am__tagged_files)'; \
-	case "$(srcdir)" in \
-	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
-	  *) sdir=$(subdir)/$(srcdir) ;; \
-	esac; \
-	for i in $$list; do \
-	  if test -f "$$i"; then \
-	    echo "$(subdir)/$$i"; \
-	  else \
-	    echo "$$sdir/$$i"; \
-	  fi; \
-	done >> $(top_builddir)/cscope.files
-
-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 "$(distdir)/$$file"; then \
-	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-	    fi; \
-	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-	    fi; \
-	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-	  else \
-	    test -f "$(distdir)/$$file" \
-	    || cp -p $$d/$$file "$(distdir)/$$file" \
-	    || exit 1; \
-	  fi; \
-	done
-	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
-	  if test "$$subdir" = .; then :; else \
-	    $(am__make_dryrun) \
-	      || test -d "$(distdir)/$$subdir" \
-	      || $(MKDIR_P) "$(distdir)/$$subdir" \
-	      || exit 1; \
-	    dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
-	    $(am__relativize); \
-	    new_distdir=$$reldir; \
-	    dir1=$$subdir; dir2="$(top_distdir)"; \
-	    $(am__relativize); \
-	    new_top_distdir=$$reldir; \
-	    echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
-	    echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
-	    ($(am__cd) $$subdir && \
-	      $(MAKE) $(AM_MAKEFLAGS) \
-	        top_distdir="$$new_top_distdir" \
-	        distdir="$$new_distdir" \
-		am__remove_distdir=: \
-		am__skip_length_check=: \
-		am__skip_mode_fix=: \
-	        distdir) \
-	      || exit 1; \
-	  fi; \
-	done
-check-am: all-am
-check: check-recursive
-all-am: Makefile $(LTLIBRARIES)
-installdirs: installdirs-recursive
-installdirs-am:
-	for dir in "$(DESTDIR)$(ipseclibdir)"; do \
-	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
-	done
-install: install-recursive
-install-exec: install-exec-recursive
-install-data: install-data-recursive
-uninstall: uninstall-recursive
-
-install-am: all-am
-	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-recursive
-install-strip:
-	if test -z '$(STRIP)'; then \
-	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-	      install; \
-	else \
-	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-	fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
-	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-	-rm -f kernel/$(DEPDIR)/$(am__dirstamp)
-	-rm -f kernel/$(am__dirstamp)
-
-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-recursive
-
-clean-am: clean-generic clean-ipseclibLTLIBRARIES clean-libtool \
-	mostlyclean-am
-
-distclean: distclean-recursive
-	-rm -rf ./$(DEPDIR) kernel/$(DEPDIR)
-	-rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
-	distclean-tags
-
-dvi: dvi-recursive
-
-dvi-am:
-
-html: html-recursive
-
-html-am:
-
-info: info-recursive
-
-info-am:
-
-install-data-am: install-ipseclibLTLIBRARIES
-
-install-dvi: install-dvi-recursive
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-recursive
-
-install-html-am:
-
-install-info: install-info-recursive
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-recursive
-
-install-pdf-am:
-
-install-ps: install-ps-recursive
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-recursive
-	-rm -rf ./$(DEPDIR) kernel/$(DEPDIR)
-	-rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-recursive
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
-	mostlyclean-libtool
-
-pdf: pdf-recursive
-
-pdf-am:
-
-ps: ps-recursive
-
-ps-am:
-
-uninstall-am: uninstall-ipseclibLTLIBRARIES
-
-.MAKE: $(am__recursive_targets) install-am install-strip
-
-.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
-	check-am clean clean-generic clean-ipseclibLTLIBRARIES \
-	clean-libtool cscopelist-am ctags ctags-am 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-ipseclibLTLIBRARIES install-man install-pdf \
-	install-pdf-am install-ps install-ps-am install-strip \
-	installcheck installcheck-am installdirs installdirs-am \
-	maintainer-clean maintainer-clean-generic mostlyclean \
-	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
-	pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
-	uninstall-ipseclibLTLIBRARIES
-
-
-# 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/libhydra/hydra.c b/src/libhydra/hydra.c
deleted file mode 100644
index 47ffb59..0000000
--- a/src/libhydra/hydra.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#include "hydra.h"
-
-#include <utils/debug.h>
-
-typedef struct private_hydra_t private_hydra_t;
-
-/**
- * Private additions to hydra_t.
- */
-struct private_hydra_t {
-
-	/**
-	 * Public members of hydra_t.
-	 */
-	hydra_t public;
-
-	/**
-	 * Integrity check failed?
-	 */
-	bool integrity_failed;
-
-	/**
-	 * Number of times we have been initialized
-	 */
-	refcount_t ref;
-};
-
-/**
- * Single instance of hydra_t.
- */
-hydra_t *hydra = NULL;
-
-/**
- * Described in header.
- */
-void libhydra_deinit()
-{
-	private_hydra_t *this = (private_hydra_t*)hydra;
-
-	if (!this || !ref_put(&this->ref))
-	{	/* have more users */
-		return;
-	}
-
-	this->public.kernel_interface->destroy(this->public.kernel_interface);
-	free(this);
-	hydra = NULL;
-}
-
-/**
- * Described in header.
- */
-bool libhydra_init()
-{
-	private_hydra_t *this;
-
-	if (hydra)
-	{	/* already initialized, increase refcount */
-		this = (private_hydra_t*)hydra;
-		ref_get(&this->ref);
-		return !this->integrity_failed;
-	}
-
-	INIT(this,
-		.ref = 1,
-	);
-	hydra = &this->public;
-
-	this->public.kernel_interface = kernel_interface_create();
-
-	if (lib->integrity &&
-		!lib->integrity->check(lib->integrity, "libhydra", libhydra_init))
-	{
-		DBG1(DBG_LIB, "integrity check of libhydra failed");
-		this->integrity_failed = TRUE;
-	}
-	return !this->integrity_failed;
-}
diff --git a/src/libhydra/hydra.h b/src/libhydra/hydra.h
deleted file mode 100644
index b23a305..0000000
--- a/src/libhydra/hydra.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-/**
- * @defgroup libhydra libhydra
- *
- * @defgroup hkernel kernel
- * @ingroup libhydra
- *
- * @defgroup hplugins plugins
- * @ingroup libhydra
- *
- * @addtogroup libhydra
- * @{
- */
-
-#ifndef HYDRA_H_
-#define HYDRA_H_
-
-typedef struct hydra_t hydra_t;
-
-#include <kernel/kernel_interface.h>
-
-#include <library.h>
-
-/**
- * IKE Daemon support object.
- */
-struct hydra_t {
-
-	/**
-	 * kernel interface to communicate with kernel
-	 */
-	kernel_interface_t *kernel_interface;
-};
-
-/**
- * The single instance of hydra_t.
- *
- * Set between calls to libhydra_init() and libhydra_deinit() calls.
- */
-extern hydra_t *hydra;
-
-/**
- * Initialize libhydra.
- *
- * libhydra_init() may be called multiple times in a single process, but each
- * caller must call libhydra_deinit() for each call to libhydra_init().
- *
- * @return				FALSE if integrity check failed
- */
-bool libhydra_init();
-
-/**
- * Deinitialize libhydra.
- */
-void libhydra_deinit();
-
-#endif /** HYDRA_H_ @}*/
diff --git a/src/libhydra/kernel/kernel_interface.c b/src/libhydra/kernel/kernel_interface.c
deleted file mode 100644
index 89e95ad..0000000
--- a/src/libhydra/kernel/kernel_interface.c
+++ /dev/null
@@ -1,1086 +0,0 @@
-/*
- * Copyright (C) 2008-2015 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
- * Copyright (C) 2010 Martin Willi
- * Copyright (C) 2010 revosec AG
- *
- * 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.
- */
-
-/*
- * Copyright (c) 2012 Nanoteq Pty Ltd
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "kernel_interface.h"
-
-#include <hydra.h>
-#include <utils/debug.h>
-#include <threading/mutex.h>
-#include <collections/linked_list.h>
-#include <collections/hashtable.h>
-#include <collections/array.h>
-
-typedef struct private_kernel_interface_t private_kernel_interface_t;
-
-typedef struct kernel_algorithm_t kernel_algorithm_t;
-
-/**
- * Mapping of IKE algorithms to kernel-specific algorithm identifiers
- */
-struct kernel_algorithm_t {
-
-	/**
-	 * Transform type of the algorithm
-	 */
-	transform_type_t type;
-
-	/**
-	 * Identifier specified in IKE
-	 */
-	u_int16_t ike;
-
-	/**
-	 * Identifier as defined in pfkeyv2.h
-	 */
-	u_int16_t kernel;
-
-	/**
-	 * Name of the algorithm in linux crypto API
-	 */
-	char *name;
-};
-
-/**
- * Private data of a kernel_interface_t object.
- */
-struct private_kernel_interface_t {
-
-	/**
-	 * Public part of kernel_interface_t object.
-	 */
-	kernel_interface_t public;
-
-	/**
-	 * Registered IPsec constructor
-	 */
-	kernel_ipsec_constructor_t ipsec_constructor;
-
-	/**
-	 * Registered net constructor
-	 */
-	kernel_net_constructor_t net_constructor;
-
-	/**
-	 * ipsec interface
-	 */
-	kernel_ipsec_t *ipsec;
-
-	/**
-	 * network interface
-	 */
-	kernel_net_t *net;
-
-	/**
-	 * mutex for listeners
-	 */
-	mutex_t *mutex;
-
-	/**
-	 * list of registered listeners
-	 */
-	linked_list_t *listeners;
-
-	/**
-	 * Reqid entries indexed by reqids
-	 */
-	hashtable_t *reqids;
-
-	/**
-	 * Reqid entries indexed by traffic selectors
-	 */
-	hashtable_t *reqids_by_ts;
-
-	/**
-	 * mutex for algorithm mappings
-	 */
-	mutex_t *mutex_algs;
-
-	/**
-	 * List of algorithm mappings (kernel_algorithm_t*)
-	 */
-	linked_list_t *algorithms;
-
-	/**
-	 * List of interface names to include or exclude (char*), NULL if interfaces
-	 * are not filtered
-	 */
-	linked_list_t *ifaces_filter;
-
-	/**
-	 * TRUE to exclude interfaces listed in ifaces_filter, FALSE to consider
-	 * only those listed there
-	 */
-	bool ifaces_exclude;
-};
-
-METHOD(kernel_interface_t, get_features, kernel_feature_t,
-	private_kernel_interface_t *this)
-{
-	kernel_feature_t features = 0;
-
-	if (this->ipsec && this->ipsec->get_features)
-	{
-		features |= this->ipsec->get_features(this->ipsec);
-	}
-	if (this->net && this->net->get_features)
-	{
-		features |= this->net->get_features(this->net);
-	}
-	return features;
-}
-
-METHOD(kernel_interface_t, get_spi, status_t,
-	private_kernel_interface_t *this, host_t *src, host_t *dst,
-	u_int8_t protocol, u_int32_t *spi)
-{
-	if (!this->ipsec)
-	{
-		return NOT_SUPPORTED;
-	}
-	return this->ipsec->get_spi(this->ipsec, src, dst, protocol, spi);
-}
-
-METHOD(kernel_interface_t, get_cpi, status_t,
-	private_kernel_interface_t *this, host_t *src, host_t *dst,
-	u_int16_t *cpi)
-{
-	if (!this->ipsec)
-	{
-		return NOT_SUPPORTED;
-	}
-	return this->ipsec->get_cpi(this->ipsec, src, dst, cpi);
-}
-
-/**
- * Reqid mapping entry
- */
-typedef struct {
-	/** allocated reqid */
-	u_int32_t reqid;
-	/** references to this entry */
-	u_int refs;
-	/** inbound mark used for SA */
-	mark_t mark_in;
-	/** outbound mark used for SA */
-	mark_t mark_out;
-	/** local traffic selectors */
-	array_t *local;
-	/** remote traffic selectors */
-	array_t *remote;
-} reqid_entry_t;
-
-/**
- * Destroy a reqid mapping entry
- */
-static void reqid_entry_destroy(reqid_entry_t *entry)
-{
-	array_destroy_offset(entry->local, offsetof(traffic_selector_t, destroy));
-	array_destroy_offset(entry->remote, offsetof(traffic_selector_t, destroy));
-	free(entry);
-}
-
-/**
- * Hashtable hash function for reqid entries using reqid as key
- */
-static u_int hash_reqid(reqid_entry_t *entry)
-{
-	return chunk_hash_inc(chunk_from_thing(entry->reqid),
-				chunk_hash_inc(chunk_from_thing(entry->mark_in),
-					chunk_hash(chunk_from_thing(entry->mark_out))));
-}
-
-/**
- * Hashtable equals function for reqid entries using reqid as key
- */
-static bool equals_reqid(reqid_entry_t *a, reqid_entry_t *b)
-{
-	return a->reqid == b->reqid &&
-		   a->mark_in.value == b->mark_in.value &&
-		   a->mark_in.mask == b->mark_in.mask &&
-		   a->mark_out.value == b->mark_out.value &&
-		   a->mark_out.mask == b->mark_out.mask;
-}
-
-/**
- * Hash an array of traffic selectors
- */
-static u_int hash_ts_array(array_t *array, u_int hash)
-{
-	enumerator_t *enumerator;
-	traffic_selector_t *ts;
-
-	enumerator = array_create_enumerator(array);
-	while (enumerator->enumerate(enumerator, &ts))
-	{
-		hash = ts->hash(ts, hash);
-	}
-	enumerator->destroy(enumerator);
-
-	return hash;
-}
-
-/**
- * Hashtable hash function for reqid entries using traffic selectors as key
- */
-static u_int hash_reqid_by_ts(reqid_entry_t *entry)
-{
-	return hash_ts_array(entry->local, hash_ts_array(entry->remote,
-			chunk_hash_inc(chunk_from_thing(entry->mark_in),
-				chunk_hash(chunk_from_thing(entry->mark_out)))));
-}
-
-/**
- * Compare two array with traffic selectors for equality
- */
-static bool ts_array_equals(array_t *a, array_t *b)
-{
-	traffic_selector_t *tsa, *tsb;
-	enumerator_t *ae, *be;
-	bool equal = TRUE;
-
-	if (array_count(a) != array_count(b))
-	{
-		return FALSE;
-	}
-
-	ae = array_create_enumerator(a);
-	be = array_create_enumerator(b);
-	while (equal && ae->enumerate(ae, &tsa) && be->enumerate(be, &tsb))
-	{
-		equal = tsa->equals(tsa, tsb);
-	}
-	ae->destroy(ae);
-	be->destroy(be);
-
-	return equal;
-}
-
-/**
- * Hashtable equals function for reqid entries using traffic selectors as key
- */
-static bool equals_reqid_by_ts(reqid_entry_t *a, reqid_entry_t *b)
-{
-	return ts_array_equals(a->local, b->local) &&
-		   ts_array_equals(a->remote, b->remote) &&
-		   a->mark_in.value == b->mark_in.value &&
-		   a->mark_in.mask == b->mark_in.mask &&
-		   a->mark_out.value == b->mark_out.value &&
-		   a->mark_out.mask == b->mark_out.mask;
-}
-
-/**
- * Create an array from copied traffic selector list items
- */
-static array_t *array_from_ts_list(linked_list_t *list)
-{
-	enumerator_t *enumerator;
-	traffic_selector_t *ts;
-	array_t *array;
-
-	array = array_create(0, 0);
-
-	enumerator = list->create_enumerator(list);
-	while (enumerator->enumerate(enumerator, &ts))
-	{
-		array_insert(array, ARRAY_TAIL, ts->clone(ts));
-	}
-	enumerator->destroy(enumerator);
-
-	return array;
-}
-
-METHOD(kernel_interface_t, alloc_reqid, status_t,
-	private_kernel_interface_t *this,
-	linked_list_t *local_ts, linked_list_t *remote_ts,
-	mark_t mark_in, mark_t mark_out, u_int32_t *reqid)
-{
-	static u_int32_t counter = 0;
-	reqid_entry_t *entry = NULL, *tmpl;
-	status_t status = SUCCESS;
-
-	INIT(tmpl,
-		.local = array_from_ts_list(local_ts),
-		.remote = array_from_ts_list(remote_ts),
-		.mark_in = mark_in,
-		.mark_out = mark_out,
-		.reqid = *reqid,
-	);
-
-	this->mutex->lock(this->mutex);
-	if (tmpl->reqid)
-	{
-		/* search by reqid if given */
-		entry = this->reqids->get(this->reqids, tmpl);
-	}
-	if (entry)
-	{
-		/* we don't require a traffic selector match for explicit reqids,
-		 * as we wan't to reuse a reqid for trap-triggered policies that
-		 * got narrowed during negotiation. */
-		reqid_entry_destroy(tmpl);
-	}
-	else
-	{
-		/* search by traffic selectors */
-		entry = this->reqids_by_ts->get(this->reqids_by_ts, tmpl);
-		if (entry)
-		{
-			reqid_entry_destroy(tmpl);
-		}
-		else
-		{
-			/* none found, create a new entry, allocating a reqid */
-			entry = tmpl;
-			entry->reqid = ++counter;
-			this->reqids_by_ts->put(this->reqids_by_ts, entry, entry);
-			this->reqids->put(this->reqids, entry, entry);
-		}
-		*reqid = entry->reqid;
-	}
-	entry->refs++;
-	this->mutex->unlock(this->mutex);
-
-	return status;
-}
-
-METHOD(kernel_interface_t, release_reqid, status_t,
-	private_kernel_interface_t *this, u_int32_t reqid,
-	mark_t mark_in, mark_t mark_out)
-{
-	reqid_entry_t *entry, tmpl = {
-		.reqid = reqid,
-		.mark_in = mark_in,
-		.mark_out = mark_out,
-	};
-
-	this->mutex->lock(this->mutex);
-	entry = this->reqids->remove(this->reqids, &tmpl);
-	if (entry)
-	{
-		if (--entry->refs == 0)
-		{
-			entry = this->reqids_by_ts->remove(this->reqids_by_ts, entry);
-			if (entry)
-			{
-				reqid_entry_destroy(entry);
-			}
-		}
-		else
-		{
-			this->reqids->put(this->reqids, entry, entry);
-		}
-	}
-	this->mutex->unlock(this->mutex);
-
-	if (entry)
-	{
-		return SUCCESS;
-	}
-	return NOT_FOUND;
-}
-
-METHOD(kernel_interface_t, add_sa, status_t,
-	private_kernel_interface_t *this, host_t *src, host_t *dst,
-	u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
-	u_int32_t tfc, lifetime_cfg_t *lifetime, 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, u_int32_t replay_window,
-	bool initiator, bool encap, bool esn, bool inbound, bool update,
-	linked_list_t *src_ts, linked_list_t *dst_ts)
-{
-	if (!this->ipsec)
-	{
-		return NOT_SUPPORTED;
-	}
-	return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid,
-				mark, tfc, lifetime, enc_alg, enc_key, int_alg, int_key, mode,
-				ipcomp, cpi, replay_window, initiator, encap, esn, inbound,
-				update, src_ts, dst_ts);
-}
-
-METHOD(kernel_interface_t, update_sa, status_t,
-	private_kernel_interface_t *this, u_int32_t spi, u_int8_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, mark_t mark)
-{
-	if (!this->ipsec)
-	{
-		return NOT_SUPPORTED;
-	}
-	return this->ipsec->update_sa(this->ipsec, spi, protocol, cpi, src, dst,
-								  new_src, new_dst, encap, new_encap, mark);
-}
-
-METHOD(kernel_interface_t, query_sa, status_t,
-	private_kernel_interface_t *this, host_t *src, host_t *dst,
-	u_int32_t spi, u_int8_t protocol, mark_t mark,
-	u_int64_t *bytes, u_int64_t *packets, time_t *time)
-{
-	if (!this->ipsec)
-	{
-		return NOT_SUPPORTED;
-	}
-	return this->ipsec->query_sa(this->ipsec, src, dst, spi, protocol, mark,
-								 bytes, packets, time);
-}
-
-METHOD(kernel_interface_t, del_sa, status_t,
-	private_kernel_interface_t *this, host_t *src, host_t *dst, u_int32_t spi,
-	u_int8_t protocol, u_int16_t cpi, mark_t mark)
-{
-	if (!this->ipsec)
-	{
-		return NOT_SUPPORTED;
-	}
-	return this->ipsec->del_sa(this->ipsec, src, dst, spi, protocol, cpi, mark);
-}
-
-METHOD(kernel_interface_t, flush_sas, status_t,
-	private_kernel_interface_t *this)
-{
-	if (!this->ipsec)
-	{
-		return NOT_SUPPORTED;
-	}
-	return this->ipsec->flush_sas(this->ipsec);
-}
-
-METHOD(kernel_interface_t, add_policy, status_t,
-	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, policy_type_t type, ipsec_sa_cfg_t *sa,
-	mark_t mark, policy_priority_t priority)
-{
-	if (!this->ipsec)
-	{
-		return NOT_SUPPORTED;
-	}
-	return this->ipsec->add_policy(this->ipsec, src, dst, src_ts, dst_ts,
-								   direction, type, sa, mark, priority);
-}
-
-METHOD(kernel_interface_t, query_policy, status_t,
-	private_kernel_interface_t *this, traffic_selector_t *src_ts,
-	traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
-	time_t *use_time)
-{
-	if (!this->ipsec)
-	{
-		return NOT_SUPPORTED;
-	}
-	return this->ipsec->query_policy(this->ipsec, src_ts, dst_ts,
-									 direction, mark, use_time);
-}
-
-METHOD(kernel_interface_t, del_policy, status_t,
-	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, policy_type_t type, ipsec_sa_cfg_t *sa,
-	mark_t mark, policy_priority_t priority)
-{
-	if (!this->ipsec)
-	{
-		return NOT_SUPPORTED;
-	}
-	return this->ipsec->del_policy(this->ipsec, src, dst, src_ts, dst_ts,
-								   direction, type, sa, mark, priority);
-}
-
-METHOD(kernel_interface_t, flush_policies, status_t,
-	private_kernel_interface_t *this)
-{
-	if (!this->ipsec)
-	{
-		return NOT_SUPPORTED;
-	}
-	return this->ipsec->flush_policies(this->ipsec);
-}
-
-METHOD(kernel_interface_t, get_source_addr, host_t*,
-	private_kernel_interface_t *this, host_t *dest, host_t *src)
-{
-	if (!this->net)
-	{
-		return NULL;
-	}
-	return this->net->get_source_addr(this->net, dest, src);
-}
-
-METHOD(kernel_interface_t, get_nexthop, host_t*,
-	private_kernel_interface_t *this, host_t *dest, int prefix, host_t *src)
-{
-	if (!this->net)
-	{
-		return NULL;
-	}
-	return this->net->get_nexthop(this->net, dest, prefix, src);
-}
-
-METHOD(kernel_interface_t, get_interface, bool,
-	private_kernel_interface_t *this, host_t *host, char **name)
-{
-	if (!this->net)
-	{
-		return NULL;
-	}
-	return this->net->get_interface(this->net, host, name);
-}
-
-METHOD(kernel_interface_t, create_address_enumerator, enumerator_t*,
-	private_kernel_interface_t *this, kernel_address_type_t which)
-{
-	if (!this->net)
-	{
-		return enumerator_create_empty();
-	}
-	return this->net->create_address_enumerator(this->net, which);
-}
-
-METHOD(kernel_interface_t, add_ip, status_t,
-	private_kernel_interface_t *this, host_t *virtual_ip, int prefix,
-	char *iface)
-{
-	if (!this->net)
-	{
-		return NOT_SUPPORTED;
-	}
-	return this->net->add_ip(this->net, virtual_ip, prefix, iface);
-}
-
-METHOD(kernel_interface_t, del_ip, status_t,
-	private_kernel_interface_t *this, host_t *virtual_ip, int prefix, bool wait)
-{
-	if (!this->net)
-	{
-		return NOT_SUPPORTED;
-	}
-	return this->net->del_ip(this->net, virtual_ip, prefix, wait);
-}
-
-METHOD(kernel_interface_t, add_route, status_t,
-	private_kernel_interface_t *this, chunk_t dst_net,
-	u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name)
-{
-	if (!this->net)
-	{
-		return NOT_SUPPORTED;
-	}
-	return this->net->add_route(this->net, dst_net, prefixlen, gateway,
-								src_ip, if_name);
-}
-
-METHOD(kernel_interface_t, del_route, status_t,
-	private_kernel_interface_t *this, chunk_t dst_net,
-	u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name)
-{
-	if (!this->net)
-	{
-		return NOT_SUPPORTED;
-	}
-	return this->net->del_route(this->net, dst_net, prefixlen, gateway,
-								src_ip, if_name);
-}
-
-METHOD(kernel_interface_t, bypass_socket, bool,
-	private_kernel_interface_t *this, int fd, int family)
-{
-	if (!this->ipsec)
-	{
-		return FALSE;
-	}
-	return this->ipsec->bypass_socket(this->ipsec, fd, family);
-}
-
-METHOD(kernel_interface_t, enable_udp_decap, bool,
-	private_kernel_interface_t *this, int fd, int family, u_int16_t port)
-{
-	if (!this->ipsec)
-	{
-		return FALSE;
-	}
-	return this->ipsec->enable_udp_decap(this->ipsec, fd, family, port);
-}
-
-METHOD(kernel_interface_t, is_interface_usable, bool,
-	private_kernel_interface_t *this, const char *iface)
-{
-	status_t expected;
-
-	if (!this->ifaces_filter)
-	{
-		return TRUE;
-	}
-	expected = this->ifaces_exclude ? NOT_FOUND : SUCCESS;
-	return this->ifaces_filter->find_first(this->ifaces_filter, (void*)streq,
-										   NULL, iface) == expected;
-}
-
-METHOD(kernel_interface_t, all_interfaces_usable, bool,
-	private_kernel_interface_t *this)
-{
-	return this->ifaces_filter == NULL;
-}
-
-METHOD(kernel_interface_t, get_address_by_ts, status_t,
-	private_kernel_interface_t *this, traffic_selector_t *ts,
-	host_t **ip, bool *vip)
-{
-	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);
-
-	/* try virtual IPs only first (on all interfaces) */
-	addrs = create_address_enumerator(this,
-									  ADDR_TYPE_ALL ^ ADDR_TYPE_REGULAR);
-	while (addrs->enumerate(addrs, (void**)&host))
-	{
-		if (ts->includes(ts, host))
-		{
-			found = TRUE;
-			*ip = host->clone(host);
-			if (vip)
-			{
-				*vip = TRUE;
-			}
-			break;
-		}
-	}
-	addrs->destroy(addrs);
-
-	if (!found)
-	{	/* then try the regular addresses (on all interfaces) */
-		addrs = create_address_enumerator(this,
-										  ADDR_TYPE_ALL ^ ADDR_TYPE_VIRTUAL);
-		while (addrs->enumerate(addrs, (void**)&host))
-		{
-			if (ts->includes(ts, host))
-			{
-				found = TRUE;
-				*ip = host->clone(host);
-				if (vip)
-				{
-					*vip = FALSE;
-				}
-				break;
-			}
-		}
-		addrs->destroy(addrs);
-	}
-
-	if (!found)
-	{
-		DBG2(DBG_KNL, "no local address found in traffic selector %R", ts);
-		return FAILED;
-	}
-
-	DBG2(DBG_KNL, "using host %H", *ip);
-	return SUCCESS;
-}
-
-
-METHOD(kernel_interface_t, add_ipsec_interface, bool,
-	private_kernel_interface_t *this, kernel_ipsec_constructor_t constructor)
-{
-	if (!this->ipsec)
-	{
-		this->ipsec_constructor = constructor;
-		this->ipsec = constructor();
-		return this->ipsec != NULL;
-	}
-	return FALSE;
-}
-
-METHOD(kernel_interface_t, remove_ipsec_interface, bool,
-	private_kernel_interface_t *this, kernel_ipsec_constructor_t constructor)
-{
-	if (constructor == this->ipsec_constructor && this->ipsec)
-	{
-		this->ipsec->destroy(this->ipsec);
-		this->ipsec = NULL;
-		return TRUE;
-	}
-	return FALSE;
-}
-
-METHOD(kernel_interface_t, add_net_interface, bool,
-	private_kernel_interface_t *this, kernel_net_constructor_t constructor)
-{
-	if (!this->net)
-	{
-		this->net_constructor = constructor;
-		this->net = constructor();
-		return this->net != NULL;
-	}
-	return FALSE;
-}
-
-METHOD(kernel_interface_t, remove_net_interface, bool,
-	private_kernel_interface_t *this, kernel_net_constructor_t constructor)
-{
-	if (constructor == this->net_constructor && this->net)
-	{
-		this->net->destroy(this->net);
-		this->net = NULL;
-		return TRUE;
-	}
-	return FALSE;
-}
-
-METHOD(kernel_interface_t, add_listener, void,
-	private_kernel_interface_t *this, kernel_listener_t *listener)
-{
-	this->mutex->lock(this->mutex);
-	this->listeners->insert_last(this->listeners, listener);
-	this->mutex->unlock(this->mutex);
-}
-
-METHOD(kernel_interface_t, remove_listener, void,
-	private_kernel_interface_t *this, kernel_listener_t *listener)
-{
-	this->mutex->lock(this->mutex);
-	this->listeners->remove(this->listeners, listener, NULL);
-	this->mutex->unlock(this->mutex);
-}
-
-METHOD(kernel_interface_t, acquire, void,
-	private_kernel_interface_t *this, u_int32_t reqid,
-	traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
-{
-	kernel_listener_t *listener;
-	enumerator_t *enumerator;
-	this->mutex->lock(this->mutex);
-	enumerator = this->listeners->create_enumerator(this->listeners);
-	while (enumerator->enumerate(enumerator, &listener))
-	{
-		if (listener->acquire &&
-			!listener->acquire(listener, reqid, src_ts, dst_ts))
-		{
-			this->listeners->remove_at(this->listeners, enumerator);
-		}
-	}
-	enumerator->destroy(enumerator);
-	this->mutex->unlock(this->mutex);
-}
-
-METHOD(kernel_interface_t, expire, void,
-	private_kernel_interface_t *this, u_int8_t protocol, u_int32_t spi,
-	host_t *dst, bool hard)
-{
-	kernel_listener_t *listener;
-	enumerator_t *enumerator;
-
-	this->mutex->lock(this->mutex);
-	enumerator = this->listeners->create_enumerator(this->listeners);
-	while (enumerator->enumerate(enumerator, &listener))
-	{
-		if (listener->expire &&
-			!listener->expire(listener, protocol, spi, dst, hard))
-		{
-			this->listeners->remove_at(this->listeners, enumerator);
-		}
-	}
-	enumerator->destroy(enumerator);
-	this->mutex->unlock(this->mutex);
-}
-
-METHOD(kernel_interface_t, mapping, void,
-	private_kernel_interface_t *this, u_int8_t protocol, u_int32_t spi,
-	host_t *dst, host_t *remote)
-{
-	kernel_listener_t *listener;
-	enumerator_t *enumerator;
-
-	this->mutex->lock(this->mutex);
-	enumerator = this->listeners->create_enumerator(this->listeners);
-	while (enumerator->enumerate(enumerator, &listener))
-	{
-		if (listener->mapping &&
-			!listener->mapping(listener, protocol, spi, dst, remote))
-		{
-			this->listeners->remove_at(this->listeners, enumerator);
-		}
-	}
-	enumerator->destroy(enumerator);
-	this->mutex->unlock(this->mutex);
-}
-
-METHOD(kernel_interface_t, migrate, void,
-	private_kernel_interface_t *this, u_int32_t reqid,
-	traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-	policy_dir_t direction, host_t *local, host_t *remote)
-{
-	kernel_listener_t *listener;
-	enumerator_t *enumerator;
-	this->mutex->lock(this->mutex);
-	enumerator = this->listeners->create_enumerator(this->listeners);
-	while (enumerator->enumerate(enumerator, &listener))
-	{
-		if (listener->migrate &&
-			!listener->migrate(listener, reqid, src_ts, dst_ts, direction,
-							   local, remote))
-		{
-			this->listeners->remove_at(this->listeners, enumerator);
-		}
-	}
-	enumerator->destroy(enumerator);
-	this->mutex->unlock(this->mutex);
-}
-
-static bool call_roam(kernel_listener_t *listener, bool *roam)
-{
-	return listener->roam && !listener->roam(listener, *roam);
-}
-
-METHOD(kernel_interface_t, roam, void,
-	private_kernel_interface_t *this, bool address)
-{
-	this->mutex->lock(this->mutex);
-	this->listeners->remove(this->listeners, &address, (void*)call_roam);
-	this->mutex->unlock(this->mutex);
-}
-
-METHOD(kernel_interface_t, tun, void,
-	private_kernel_interface_t *this, tun_device_t *tun, bool created)
-{
-	kernel_listener_t *listener;
-	enumerator_t *enumerator;
-	this->mutex->lock(this->mutex);
-	enumerator = this->listeners->create_enumerator(this->listeners);
-	while (enumerator->enumerate(enumerator, &listener))
-	{
-		if (listener->tun &&
-			!listener->tun(listener, tun, created))
-		{
-			this->listeners->remove_at(this->listeners, enumerator);
-		}
-	}
-	enumerator->destroy(enumerator);
-	this->mutex->unlock(this->mutex);
-}
-
-METHOD(kernel_interface_t, register_algorithm, void,
-	private_kernel_interface_t *this, u_int16_t alg_id, transform_type_t type,
-	u_int16_t kernel_id, char *kernel_name)
-{
-	kernel_algorithm_t *algorithm;
-
-	INIT(algorithm,
-		.type = type,
-		.ike = alg_id,
-		.kernel = kernel_id,
-		.name = strdup(kernel_name),
-	);
-
-	this->mutex_algs->lock(this->mutex_algs);
-	this->algorithms->insert_first(this->algorithms, algorithm);
-	this->mutex_algs->unlock(this->mutex_algs);
-}
-
-METHOD(kernel_interface_t, lookup_algorithm, bool,
-	private_kernel_interface_t *this, u_int16_t alg_id, transform_type_t type,
-	u_int16_t *kernel_id, char **kernel_name)
-{
-	kernel_algorithm_t *algorithm;
-	enumerator_t *enumerator;
-	bool found = FALSE;
-
-	this->mutex_algs->lock(this->mutex_algs);
-	enumerator = this->algorithms->create_enumerator(this->algorithms);
-	while (enumerator->enumerate(enumerator, &algorithm))
-	{
-		if (algorithm->type == type && algorithm->ike == alg_id)
-		{
-			if (kernel_id)
-			{
-				*kernel_id = algorithm->kernel;
-			}
-			if (kernel_name)
-			{
-				*kernel_name = algorithm->name;
-			}
-			found = TRUE;
-			break;
-		}
-	}
-	enumerator->destroy(enumerator);
-	this->mutex_algs->unlock(this->mutex_algs);
-	return found;
-}
-
-METHOD(kernel_interface_t, destroy, void,
-	private_kernel_interface_t *this)
-{
-	kernel_algorithm_t *algorithm;
-
-	while (this->algorithms->remove_first(this->algorithms,
-										 (void**)&algorithm) == SUCCESS)
-	{
-		free(algorithm->name);
-		free(algorithm);
-	}
-	this->algorithms->destroy(this->algorithms);
-	this->mutex_algs->destroy(this->mutex_algs);
-	DESTROY_IF(this->ipsec);
-	DESTROY_IF(this->net);
-	DESTROY_FUNCTION_IF(this->ifaces_filter, (void*)free);
-	this->reqids->destroy(this->reqids);
-	this->reqids_by_ts->destroy(this->reqids_by_ts);
-	this->listeners->destroy(this->listeners);
-	this->mutex->destroy(this->mutex);
-	free(this);
-}
-
-/*
- * Described in header-file
- */
-kernel_interface_t *kernel_interface_create()
-{
-	private_kernel_interface_t *this;
-	char *ifaces;
-
-	INIT(this,
-		.public = {
-			.get_features = _get_features,
-			.get_spi = _get_spi,
-			.get_cpi = _get_cpi,
-			.alloc_reqid = _alloc_reqid,
-			.release_reqid = _release_reqid,
-			.add_sa = _add_sa,
-			.update_sa = _update_sa,
-			.query_sa = _query_sa,
-			.del_sa = _del_sa,
-			.flush_sas = _flush_sas,
-			.add_policy = _add_policy,
-			.query_policy = _query_policy,
-			.del_policy = _del_policy,
-			.flush_policies = _flush_policies,
-			.get_source_addr = _get_source_addr,
-			.get_nexthop = _get_nexthop,
-			.get_interface = _get_interface,
-			.create_address_enumerator = _create_address_enumerator,
-			.add_ip = _add_ip,
-			.del_ip = _del_ip,
-			.add_route = _add_route,
-			.del_route = _del_route,
-			.bypass_socket = _bypass_socket,
-			.enable_udp_decap = _enable_udp_decap,
-
-			.is_interface_usable = _is_interface_usable,
-			.all_interfaces_usable = _all_interfaces_usable,
-			.get_address_by_ts = _get_address_by_ts,
-			.add_ipsec_interface = _add_ipsec_interface,
-			.remove_ipsec_interface = _remove_ipsec_interface,
-			.add_net_interface = _add_net_interface,
-			.remove_net_interface = _remove_net_interface,
-
-			.add_listener = _add_listener,
-			.remove_listener = _remove_listener,
-			.register_algorithm = _register_algorithm,
-			.lookup_algorithm = _lookup_algorithm,
-			.acquire = _acquire,
-			.expire = _expire,
-			.mapping = _mapping,
-			.migrate = _migrate,
-			.roam = _roam,
-			.tun = _tun,
-			.destroy = _destroy,
-		},
-		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
-		.listeners = linked_list_create(),
-		.mutex_algs = mutex_create(MUTEX_TYPE_DEFAULT),
-		.algorithms = linked_list_create(),
-		.reqids = hashtable_create((hashtable_hash_t)hash_reqid,
-								   (hashtable_equals_t)equals_reqid, 8),
-		.reqids_by_ts = hashtable_create((hashtable_hash_t)hash_reqid_by_ts,
-								   (hashtable_equals_t)equals_reqid_by_ts, 8),
-	);
-
-	ifaces = lib->settings->get_str(lib->settings,
-									"%s.interfaces_use", NULL, lib->ns);
-	if (!ifaces)
-	{
-		this->ifaces_exclude = TRUE;
-		ifaces = lib->settings->get_str(lib->settings,
-									"%s.interfaces_ignore", NULL, lib->ns);
-	}
-	if (ifaces)
-	{
-		enumerator_t *enumerator;
-		char *iface;
-
-		enumerator = enumerator_create_token(ifaces, ",", " ");
-		while (enumerator->enumerate(enumerator, &iface))
-		{
-			if (!this->ifaces_filter)
-			{
-				this->ifaces_filter = linked_list_create();
-			}
-			this->ifaces_filter->insert_last(this->ifaces_filter,
-											 strdup(iface));
-		}
-		enumerator->destroy(enumerator);
-	}
-
-	return &this->public;
-}
diff --git a/src/libhydra/kernel/kernel_interface.h b/src/libhydra/kernel/kernel_interface.h
deleted file mode 100644
index 45efe89..0000000
--- a/src/libhydra/kernel/kernel_interface.h
+++ /dev/null
@@ -1,655 +0,0 @@
-/*
- * Copyright (C) 2006-2015 Tobias Brunner
- * Copyright (C) 2006 Daniel Roethlisberger
- * Copyright (C) 2005-2006 Martin Willi
- * Copyright (C) 2005 Jan Hutter
- * 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.
- */
-
-/*
- * Copyright (c) 2012 Nanoteq Pty Ltd
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-/**
- * @defgroup kernel_interface kernel_interface
- * @{ @ingroup hkernel
- */
-
-#ifndef KERNEL_INTERFACE_H_
-#define KERNEL_INTERFACE_H_
-
-typedef struct kernel_interface_t kernel_interface_t;
-typedef enum kernel_feature_t kernel_feature_t;
-
-#include <networking/host.h>
-#include <crypto/prf_plus.h>
-
-#include <kernel/kernel_listener.h>
-#include <kernel/kernel_ipsec.h>
-#include <kernel/kernel_net.h>
-
-/**
- * Bitfield of optional features a kernel backend supports.
- *
- * This feature-set is for both, kernel_ipsec_t and kernel_net_t. Each
- * backend returns a subset of these features.
- */
-enum kernel_feature_t {
-	/** IPsec can process ESPv3 (RFC 4303) TFC padded packets */
-	KERNEL_ESP_V3_TFC = (1<<0),
-	/** Networking requires an "exclude" route for IKE/ESP packets */
-	KERNEL_REQUIRE_EXCLUDE_ROUTE = (1<<1),
-	/** IPsec implementation requires UDP encapsulation of ESP packets */
-	KERNEL_REQUIRE_UDP_ENCAPSULATION = (1<<2),
-	/** IPsec backend does not require a policy reinstall on SA updates */
-	KERNEL_NO_POLICY_UPDATES = (1<<3),
-};
-
-/**
- * Constructor function for ipsec kernel interface
- */
-typedef kernel_ipsec_t* (*kernel_ipsec_constructor_t)(void);
-
-/**
- * Constructor function for network kernel interface
- */
-typedef kernel_net_t* (*kernel_net_constructor_t)(void);
-
-/**
- * Manager and wrapper for different kernel interfaces.
- *
- * The kernel interface handles the communication with the kernel
- * for SA and policy management and interface and IP address management.
- */
-struct kernel_interface_t {
-
-	/**
-	 * Get the feature set supported by the net and ipsec kernel backends.
-	 *
-	 * @return				ORed feature-set of backends
-	 */
-	kernel_feature_t (*get_features)(kernel_interface_t *this);
-
-	/**
-	 * Get a SPI from the kernel.
-	 *
-	 * @param src		source address of SA
-	 * @param dst		destination address of SA
-	 * @param protocol	protocol for SA (ESP/AH)
-	 * @param spi		allocated spi
-	 * @return			SUCCESS if operation completed
-	 */
-	status_t (*get_spi)(kernel_interface_t *this, host_t *src, host_t *dst,
-						u_int8_t protocol, u_int32_t *spi);
-
-	/**
-	 * Get a Compression Parameter Index (CPI) from the kernel.
-	 *
-	 * @param src		source address of SA
-	 * @param dst		destination address of SA
-	 * @param cpi		allocated cpi
-	 * @return			SUCCESS if operation completed
-	 */
-	status_t (*get_cpi)(kernel_interface_t *this, host_t *src, host_t *dst,
-						u_int16_t *cpi);
-
-	/**
-	 * Allocate or confirm a reqid to use for a given SA pair.
-	 *
-	 * Each returned reqid by a successful call to alloc_reqid() must be
-	 * released using release_reqid().
-	 *
-	 * The reqid parameter is an in/out parameter. If it points to non-zero,
-	 * the reqid is confirmed and registered for use. If it points to zero,
-	 * a reqid is allocated for the given selectors, and returned to reqid.
-	 *
-	 * @param local_ts	traffic selectors of local side for SA
-	 * @param remote_ts	traffic selectors of remote side for SA
-	 * @param mark_in	inbound mark on SA
-	 * @param mark_out	outbound mark on SA
-	 * @param reqid		allocated reqid
-	 * @return			SUCCESS if reqid allocated
-	 */
-	status_t (*alloc_reqid)(kernel_interface_t *this,
-							linked_list_t *local_ts, linked_list_t *remote_ts,
-							mark_t mark_in, mark_t mark_out,
-							u_int32_t *reqid);
-
-	/**
-	 * Release a previously allocated reqid.
-	 *
-	 * @param reqid		reqid to release
-	 * @param mark_in	inbound mark on SA
-	 * @param mark_out	outbound mark on SA
-	 * @return			SUCCESS if reqid released
-	 */
-	status_t (*release_reqid)(kernel_interface_t *this, u_int32_t reqid,
-							  mark_t mark_in, mark_t mark_out);
-
-	/**
-	 * Add an SA to the SAD.
-	 *
-	 * This function does install a single SA for a single protocol in one
-	 * direction.
-	 *
-	 * @param src			source address for this 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 reqid			reqid for this SA
-	 * @param mark			optional mark for this SA
-	 * @param tfc			Traffic Flow Confidentiality padding for this SA
-	 * @param lifetime		lifetime_cfg_t for this SA
-	 * @param enc_alg		Algorithm to use for encryption (ESP only)
-	 * @param enc_key		key to use for encryption
-	 * @param int_alg		Algorithm to use for integrity protection
-	 * @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 replay_window	anti-replay window size
-	 * @param initiator		TRUE if initiator of the exchange creating this SA
-	 * @param encap			enable UDP encapsulation for NAT traversal
-	 * @param esn			TRUE to use Extended Sequence Numbers
-	 * @param inbound		TRUE if this is an inbound SA
-	 * @param update		TRUE if an SPI has already been allocated for SA
-	 * @param src_ts		list of source traffic selectors
-	 * @param dst_ts		list of destination traffic selectors
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*add_sa) (kernel_interface_t *this,
-						host_t *src, host_t *dst, u_int32_t spi,
-						u_int8_t protocol, u_int32_t reqid, mark_t mark,
-						u_int32_t tfc, lifetime_cfg_t *lifetime,
-						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,
-						u_int32_t replay_window, bool initiator, bool encap,
-						bool esn, bool inbound, bool update,
-						linked_list_t *src_ts, linked_list_t *dst_ts);
-
-	/**
-	 * Update the hosts on an installed SA.
-	 *
-	 * We cannot directly update the destination address as the kernel
-	 * requires the spi, the protocol AND the destination address (and family)
-	 * to identify SAs. Therefore if the destination address changed we
-	 * create a new SA and delete the old one.
-	 *
-	 * @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			current use of UDP encapsulation
-	 * @param new_encap		new use of UDP encapsulation
-	 * @param mark			optional mark for this SA
-	 * @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, u_int8_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, mark_t mark);
-
-	/**
-	 * Query the number of bytes processed by an SA from the SAD.
-	 *
-	 * @param src			source address for this 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 mark			optional mark for this SA
-	 * @param[out] bytes	the number of bytes processed by SA
-	 * @param[out] packets	number of packets processed by SA
-	 * @param[out] time		last (monotonic) time of SA use
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*query_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
-						  u_int32_t spi, u_int8_t protocol, mark_t mark,
-						  u_int64_t *bytes, u_int64_t *packets, time_t *time);
-
-	/**
-	 * Delete a previously installed SA from the SAD.
-	 *
-	 * @param src			source address for this 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 cpi			CPI for IPComp or 0
-	 * @param mark			optional mark for this SA
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*del_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
-						u_int32_t spi, u_int8_t protocol, u_int16_t cpi,
-						mark_t mark);
-
-	/**
-	 * Flush all SAs from the SAD.
-	 *
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*flush_sas) (kernel_interface_t *this);
-
-	/**
-	 * Add a policy to the SPD.
-	 *
-	 * @param src			source address of SA
-	 * @param dst			dest address of SA
-	 * @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|OUT|FWD)
-	 * @param type			type of policy, POLICY_(IPSEC|PASS|DROP)
-	 * @param sa			details about the SA(s) tied to this policy
-	 * @param mark			mark for this policy
-	 * @param priority		priority of this policy
-	 * @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, policy_type_t type,
-							ipsec_sa_cfg_t *sa, mark_t mark,
-							policy_priority_t priority);
-
-	/**
-	 * Query the use time of a policy.
-	 *
-	 * The use time of a policy is the time the policy was used
-	 * for the last time.
-	 *
-	 * @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|OUT|FWD)
-	 * @param mark			optional mark
-	 * @param[out] use_time	the (monotonic) time of this SA's last use
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*query_policy) (kernel_interface_t *this,
-							  traffic_selector_t *src_ts,
-							  traffic_selector_t *dst_ts,
-							  policy_dir_t direction, mark_t mark,
-							  time_t *use_time);
-
-	/**
-	 * Remove a policy from the SPD.
-	 *
-	 * @param src			source address of SA
-	 * @param dst			dest address of SA
-	 * @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|OUT|FWD)
-	 * @param type			type of policy, POLICY_(IPSEC|PASS|DROP)
-	 * @param sa			details about the SA(s) tied to this policy
-	 * @param mark			mark for this policy
-	 * @param priority		priority of the policy
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*del_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, policy_type_t type,
-							ipsec_sa_cfg_t *sa, mark_t mark,
-							policy_priority_t priority);
-
-	/**
-	 * Flush all policies from the SPD.
-	 *
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*flush_policies) (kernel_interface_t *this);
-
-	/**
-	 * Get our outgoing source address for a destination.
-	 *
-	 * Does a route lookup to get the source address used to reach dest.
-	 * The returned host is allocated and must be destroyed.
-	 * An optional src address can be used to check if a route is available
-	 * for the given source to dest.
-	 *
-	 * @param dest			target destination address
-	 * @param src			source address to check, or NULL
-	 * @return				outgoing source address, NULL if unreachable
-	 */
-	host_t* (*get_source_addr)(kernel_interface_t *this,
-							   host_t *dest, host_t *src);
-
-	/**
-	 * Get the next hop for a destination.
-	 *
-	 * Does a route lookup to get the next hop used to reach dest.
-	 * The returned host is allocated and must be destroyed.
-	 * An optional src address can be used to check if a route is available
-	 * for the given source to dest.
-	 *
-	 * @param dest			target destination address
-	 * @param prefix		prefix length if dest is a subnet, -1 for auto
-	 * @param src			source address to check, or NULL
-	 * @return				next hop address, NULL if unreachable
-	 */
-	host_t* (*get_nexthop)(kernel_interface_t *this, host_t *dest,
-						   int prefix, host_t *src);
-
-	/**
-	 * Get the interface name of a local address. Interfaces that are down or
-	 * ignored by config are not considered.
-	 *
-	 * @param host			address to get interface name from
-	 * @param name			allocated interface name (optional)
-	 * @return				TRUE if interface found and usable
-	 */
-	bool (*get_interface)(kernel_interface_t *this, host_t *host, char **name);
-
-	/**
-	 * Creates an enumerator over all local addresses.
-	 *
-	 * This function blocks an internal cached address list until the
-	 * enumerator gets destroyed.
-	 * The hosts are read-only, do not modify of free.
-	 *
-	 * @param which			a combination of address types to enumerate
-	 * @return				enumerator over host_t's
-	 */
-	enumerator_t *(*create_address_enumerator) (kernel_interface_t *this,
-												kernel_address_type_t which);
-
-	/**
-	 * Add a virtual IP to an interface.
-	 *
-	 * Virtual IPs are attached to an interface. If an IP is added multiple
-	 * times, the IP is refcounted and not removed until del_ip() was called
-	 * as many times as add_ip().
-	 *
-	 * @param virtual_ip	virtual ip address to assign
-	 * @param prefix		prefix length to install IP with, -1 for auto
-	 * @param iface			interface to install virtual IP on
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*add_ip) (kernel_interface_t *this, host_t *virtual_ip, int prefix,
-						char *iface);
-
-	/**
-	 * Remove a virtual IP from an interface.
-	 *
-	 * The kernel interface uses refcounting, see add_ip().
-	 *
-	 * @param virtual_ip	virtual ip address to remove
-	 * @param prefix		prefix length of the IP to uninstall, -1 for auto
-	 * @param wait			TRUE to wait untily IP is gone
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*del_ip) (kernel_interface_t *this, host_t *virtual_ip,
-						int prefix, bool wait);
-
-	/**
-	 * Add a route.
-	 *
-	 * @param dst_net		destination net
-	 * @param prefixlen		destination net prefix length
-	 * @param gateway		gateway for this route
-	 * @param src_ip		source ip of the route
-	 * @param if_name		name of the interface the route is bound to
-	 * @return				SUCCESS if operation completed
-	 *						ALREADY_DONE if the route already exists
-	 */
-	status_t (*add_route) (kernel_interface_t *this, chunk_t dst_net,
-						   u_int8_t prefixlen, host_t *gateway, host_t *src_ip,
-						   char *if_name);
-
-	/**
-	 * Delete a route.
-	 *
-	 * @param dst_net		destination net
-	 * @param prefixlen		destination net prefix length
-	 * @param gateway		gateway for this route
-	 * @param src_ip		source ip of the route
-	 * @param if_name		name of the interface the route is bound to
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*del_route) (kernel_interface_t *this, chunk_t dst_net,
-						   u_int8_t prefixlen, host_t *gateway, host_t *src_ip,
-						   char *if_name);
-
-	/**
-	 * Set up a bypass policy for a given socket.
-	 *
-	 * @param fd			socket file descriptor to setup policy for
-	 * @param family		protocol family of the socket
-	 * @return				TRUE if policy set up successfully
-	 */
-	bool (*bypass_socket)(kernel_interface_t *this, int fd, int family);
-
-	/**
-	 * Enable decapsulation of ESP-in-UDP packets for the given port/socket.
-	 *
-	 * @param fd			socket file descriptor
-	 * @param family		protocol family of the socket
-	 * @param port			the UDP port
-	 * @return				TRUE if UDP decapsulation was enabled successfully
-	 */
-	bool (*enable_udp_decap)(kernel_interface_t *this, int fd, int family,
-							 u_int16_t port);
-
-
-	/**
-	 * manager methods
-	 */
-
-	/**
-	 * Verifies that the given interface is usable and not excluded by
-	 * configuration.
-	 *
-	 * @param iface			interface name
-	 * @return				TRUE if usable
-	 */
-	bool (*is_interface_usable)(kernel_interface_t *this, const char *iface);
-
-	/**
-	 * Check if interfaces are excluded by config.
-	 *
-	 * @return				TRUE if no interfaces are exclued by config
-	 */
-	bool (*all_interfaces_usable)(kernel_interface_t *this);
-
-	/**
-	 * 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 address (has to be destroyed)
-	 * @param vip			set to TRUE if returned address is a virtual IP
-	 * @return				SUCCESS if address found
-	 */
-	status_t (*get_address_by_ts)(kernel_interface_t *this,
-								  traffic_selector_t *ts, host_t **ip, bool *vip);
-
-	/**
-	 * Register an ipsec kernel interface constructor on the manager.
-	 *
-	 * @param create		constructor to register
-	 * @return				TRUE if the ipsec kernel interface was registered
-	 *						successfully, FALSE if an interface was already
-	 *						registered or the registration failed
-	 */
-	bool (*add_ipsec_interface)(kernel_interface_t *this,
-								kernel_ipsec_constructor_t create);
-
-	/**
-	 * Unregister an ipsec kernel interface constructor.
-	 *
-	 * @param create		constructor to unregister
-	 * @return				TRUE if the ipsec kernel interface was unregistered
-	 *						successfully, FALSE otherwise
-	 */
-	bool (*remove_ipsec_interface)(kernel_interface_t *this,
-								   kernel_ipsec_constructor_t create);
-
-	/**
-	 * Register a network kernel interface constructor on the manager.
-	 *
-	 * @param create		constructor to register
-	 * @return				TRUE if the kernel net interface was registered
-	 *						successfully, FALSE if an interface was already
-	 *						registered or the registration failed
-	 */
-	bool (*add_net_interface)(kernel_interface_t *this,
-							  kernel_net_constructor_t create);
-
-	/**
-	 * Unregister a network kernel interface constructor.
-	 *
-	 * @param create		constructor to unregister
-	 * @return				TRUE if the kernel net interface was unregistered
-	 *						successfully, FALSE otherwise
-	 */
-	bool (*remove_net_interface)(kernel_interface_t *this,
-								 kernel_net_constructor_t create);
-
-	/**
-	 * Add a listener to the kernel interface.
-	 *
-	 * @param listener		listener to add
-	 */
-	void (*add_listener)(kernel_interface_t *this,
-						 kernel_listener_t *listener);
-
-	/**
-	 * Remove a listener from the kernel interface.
-	 *
-	 * @param listener		listener to remove
-	 */
-	void (*remove_listener)(kernel_interface_t *this,
-							kernel_listener_t *listener);
-
-	/**
-	 * Raise an acquire event.
-	 *
-	 * @param reqid			reqid of the policy to acquire
-	 * @param src_ts		source traffic selector
-	 * @param dst_ts		destination traffic selector
-	 */
-	void (*acquire)(kernel_interface_t *this, u_int32_t reqid,
-					traffic_selector_t *src_ts, traffic_selector_t *dst_ts);
-
-	/**
-	 * Raise an expire event.
-	 *
-	 * @param protocol		protocol of the expired SA
-	 * @param spi			spi of the expired SA
-	 * @param dst			destination address of expired SA
-	 * @param hard			TRUE if it is a hard expire, FALSE otherwise
-	 */
-	void (*expire)(kernel_interface_t *this, u_int8_t protocol, u_int32_t spi,
-				   host_t *dst, bool hard);
-
-	/**
-	 * Raise a mapping event.
-	 *
-	 * @param protocol		protocol of affected SA
-	 * @param spi			spi of the SA
-	 * @param dst			original destination address of SA
-	 * @param remote		new remote host
-	 */
-	void (*mapping)(kernel_interface_t *this, u_int8_t protocol, u_int32_t spi,
-					host_t *dst, host_t *remote);
-
-	/**
-	 * Raise a migrate event.
-	 *
-	 * @param reqid			reqid of the policy
-	 * @param src_ts		source traffic selector
-	 * @param dst_ts		destination traffic selector
-	 * @param direction		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
-	 */
-	void (*migrate)(kernel_interface_t *this, u_int32_t reqid,
-					traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-					policy_dir_t direction, host_t *local, host_t *remote);
-
-	/**
-	 * Raise a roam event.
-	 *
-	 * @param address		TRUE if address list, FALSE if routing changed
-	 */
-	void (*roam)(kernel_interface_t *this, bool address);
-
-	/**
-	 * Raise a tun event.
-	 *
-	 * @param tun			TUN device
-	 * @param created		TRUE if created, FALSE if going to be destroyed
-	 */
-	void (*tun)(kernel_interface_t *this, tun_device_t *tun, bool created);
-
-	/**
-	 * Register a new algorithm with the kernel interface.
-	 *
-	 * @param alg_id			the IKE id of the algorithm
-	 * @param type				the transform type of the algorithm
-	 * @param kernel_id			the kernel id of the algorithm
-	 * @param kernel_name		the kernel name of the algorithm
-	 */
-	void (*register_algorithm)(kernel_interface_t *this, u_int16_t alg_id,
-							   transform_type_t type, u_int16_t kernel_id,
-							   char *kernel_name);
-
-	/**
-	 * Return the kernel-specific id and/or name for an algorithms depending on
-	 * the arguments specified.
-	 *
-	 * @param alg_id			the IKE id of the algorithm
-	 * @param type				the transform type of the algorithm
-	 * @param kernel_id			the kernel id of the algorithm (optional)
-	 * @param kernel_name		the kernel name of the algorithm (optional)
-	 * @return					TRUE if algorithm was found
-	 */
-	bool (*lookup_algorithm)(kernel_interface_t *this, u_int16_t alg_id,
-							 transform_type_t type, u_int16_t *kernel_id,
-							 char **kernel_name);
-
-	/**
-	 * Destroys a kernel_interface_t object.
-	 */
-	void (*destroy) (kernel_interface_t *this);
-};
-
-/**
- * Creates an object of type kernel_interface_t.
- */
-kernel_interface_t *kernel_interface_create(void);
-
-#endif /** KERNEL_INTERFACE_H_ @}*/
diff --git a/src/libhydra/kernel/kernel_ipsec.c b/src/libhydra/kernel/kernel_ipsec.c
deleted file mode 100644
index 697b1b3..0000000
--- a/src/libhydra/kernel/kernel_ipsec.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.
- */
-
-#include "kernel_ipsec.h"
-
-#include <hydra.h>
-
-/**
- * See header
- */
-bool kernel_ipsec_register(plugin_t *plugin, plugin_feature_t *feature,
-						   bool reg, void *data)
-{
-	if (reg)
-	{
-		return hydra->kernel_interface->add_ipsec_interface(
-											hydra->kernel_interface,
-											(kernel_ipsec_constructor_t)data);
-	}
-	else
-	{
-		return hydra->kernel_interface->remove_ipsec_interface(
-											hydra->kernel_interface,
-											(kernel_ipsec_constructor_t)data);
-	}
-}
diff --git a/src/libhydra/kernel/kernel_ipsec.h b/src/libhydra/kernel/kernel_ipsec.h
deleted file mode 100644
index 2458db5..0000000
--- a/src/libhydra/kernel/kernel_ipsec.h
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright (C) 2006-2015 Tobias Brunner
- * Copyright (C) 2006 Daniel Roethlisberger
- * Copyright (C) 2005-2006 Martin Willi
- * Copyright (C) 2005 Jan Hutter
- * 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 kernel_ipsec kernel_ipsec
- * @{ @ingroup hkernel
- */
-
-#ifndef KERNEL_IPSEC_H_
-#define KERNEL_IPSEC_H_
-
-typedef struct kernel_ipsec_t kernel_ipsec_t;
-
-#include <networking/host.h>
-#include <ipsec/ipsec_types.h>
-#include <selectors/traffic_selector.h>
-#include <plugins/plugin.h>
-#include <kernel/kernel_interface.h>
-
-/**
- * Interface to the ipsec subsystem of the kernel.
- *
- * The kernel ipsec interface handles the communication with the kernel
- * for SA and policy management. It allows setup of these, and provides
- * further the handling of kernel events.
- * Policy information are cached in the interface. This is necessary to do
- * reference counting. The Linux kernel does not allow the same policy
- * installed twice, but we need this as CHILD_SA exist multiple times
- * when rekeying. Thats why we do reference counting of policies.
- */
-struct kernel_ipsec_t {
-
-	/**
-	 * Get the feature set supported by this kernel backend.
-	 *
-	 * @return				ORed feature-set of backend
-	 */
-	kernel_feature_t (*get_features)(kernel_ipsec_t *this);
-
-	/**
-	 * Get a SPI from the kernel.
-	 *
-	 * @param src		source address of SA
-	 * @param dst		destination address of SA
-	 * @param protocol	protocol for SA (ESP/AH)
-	 * @param spi		allocated spi
-	 * @return			SUCCESS if operation completed
-	 */
-	status_t (*get_spi)(kernel_ipsec_t *this, host_t *src, host_t *dst,
-						u_int8_t protocol, u_int32_t *spi);
-
-	/**
-	 * Get a Compression Parameter Index (CPI) from the kernel.
-	 *
-	 * @param src		source address of SA
-	 * @param dst		destination address of SA
-	 * @param cpi		allocated cpi
-	 * @return			SUCCESS if operation completed
-	 */
-	status_t (*get_cpi)(kernel_ipsec_t *this, host_t *src, host_t *dst,
-						u_int16_t *cpi);
-
-	/**
-	 * Add an SA to the SAD.
-	 *
-	 * This function does install a single SA for a single protocol in one
-	 * direction.
-	 *
-	 * @param src			source address for this 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 reqid			unique ID for this SA
-	 * @param mark			mark for this SA
-	 * @param tfc			Traffic Flow Confidentiality padding for this SA
-	 * @param lifetime		lifetime_cfg_t for this SA
-	 * @param enc_alg		Algorithm to use for encryption (ESP only)
-	 * @param enc_key		key to use for encryption
-	 * @param int_alg		Algorithm to use for integrity protection
-	 * @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 replay_window	anti-replay window size
-	 * @param initiator		TRUE if initiator of the exchange creating this SA
-	 * @param encap			enable UDP encapsulation for NAT traversal
-	 * @param esn			TRUE to use Extended Sequence Numbers
-	 * @param inbound		TRUE if this is an inbound SA
-	 * @param update		TRUE if an SPI has already been allocated for SA
-	 * @param src_ts		list of source traffic selectors
-	 * @param dst_ts		list of destination traffic selectors
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*add_sa) (kernel_ipsec_t *this,
-						host_t *src, host_t *dst, u_int32_t spi,
-						u_int8_t protocol, u_int32_t reqid,
-						mark_t mark, u_int32_t tfc, lifetime_cfg_t *lifetime,
-						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,
-						u_int32_t replay_window, bool initiator, bool encap,
-						bool esn, bool inbound, bool update,
-						linked_list_t *src_ts, linked_list_t *dst_ts);
-
-	/**
-	 * Update the hosts on an installed SA.
-	 *
-	 * We cannot directly update the destination address as the kernel
-	 * requires the spi, the protocol AND the destination address (and family)
-	 * to identify SAs. Therefore if the destination address changed we
-	 * create a new SA and delete the old one.
-	 *
-	 * @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			current use of UDP encapsulation
-	 * @param new_encap		new use of UDP encapsulation
-	 * @param mark			optional mark for this SA
-	 * @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, u_int8_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, mark_t mark);
-
-	/**
-	 * Query the number of bytes processed by an SA from the SAD.
-	 *
-	 * @param src			source address for this 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 mark			optional mark for this SA
-	 * @param[out] bytes	the number of bytes processed by SA
-	 * @param[out] packets	number of packets processed by SA
-	 * @param[out] time		last (monotonic) time of SA use
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*query_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
-						  u_int32_t spi, u_int8_t protocol, mark_t mark,
-						  u_int64_t *bytes, u_int64_t *packets, time_t *time);
-
-	/**
-	 * Delete a previusly installed SA from the SAD.
-	 *
-	 * @param src			source address for this 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 cpi			CPI for IPComp or 0
-	 * @param mark			optional mark for this SA
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*del_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
-						u_int32_t spi, u_int8_t protocol, u_int16_t cpi,
-						mark_t mark);
-
-	/**
-	 * Flush all SAs from the SAD.
-	 *
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*flush_sas) (kernel_ipsec_t *this);
-
-	/**
-	 * Add a policy to the SPD.
-	 *
-	 * @param src			source address of SA
-	 * @param dst			dest address of SA
-	 * @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|OUT|FWD)
-	 * @param type			type of policy, POLICY_(IPSEC|PASS|DROP)
-	 * @param sa			details about the SA(s) tied to this policy
-	 * @param mark			mark for this policy
-	 * @param priority		priority of this policy
-	 * @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, policy_type_t type,
-							ipsec_sa_cfg_t *sa, mark_t mark,
-							policy_priority_t priority);
-
-	/**
-	 * Query the use time of a policy.
-	 *
-	 * The use time of a policy is the time the policy was used for the last
-	 * time. It is not the system time, but a monotonic timestamp as returned
-	 * by time_monotonic.
-	 *
-	 * @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|OUT|FWD)
-	 * @param mark			optional mark
-	 * @param[out] use_time	the monotonic timestamp of this SA's last use
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*query_policy) (kernel_ipsec_t *this,
-							  traffic_selector_t *src_ts,
-							  traffic_selector_t *dst_ts,
-							  policy_dir_t direction, mark_t mark,
-							  time_t *use_time);
-
-	/**
-	 * Remove a policy from the SPD.
-	 *
-	 * @param src			source address of SA
-	 * @param dst			dest address of SA
-	 * @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|OUT|FWD)
-	 * @param type			type of policy, POLICY_(IPSEC|PASS|DROP)
-	 * @param sa			details about the SA(s) tied to this policy
-	 * @param mark			mark for this policy
-	 * @param priority		priority of the policy
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*del_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, policy_type_t type,
-							ipsec_sa_cfg_t *sa, mark_t mark,
-							policy_priority_t priority);
-
-	/**
-	 * Flush all policies from the SPD.
-	 *
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*flush_policies) (kernel_ipsec_t *this);
-
-	/**
-	 * Install a bypass policy for the given socket.
-	 *
-	 * @param fd			socket file descriptor to setup policy for
-	 * @param family		protocol family of the socket
-	 * @return				TRUE of policy set up successfully
-	 */
-	bool (*bypass_socket)(kernel_ipsec_t *this, int fd, int family);
-
-	/**
-	 * Enable decapsulation of ESP-in-UDP packets for the given port/socket.
-	 *
-	 * @param fd			socket file descriptor
-	 * @param family		protocol family of the socket
-	 * @param port			the UDP port
-	 * @return				TRUE if UDP decapsulation was enabled successfully
-	 */
-	bool (*enable_udp_decap)(kernel_ipsec_t *this, int fd, int family,
-							 u_int16_t port);
-
-	/**
-	 * Destroy the implementation.
-	 */
-	void (*destroy) (kernel_ipsec_t *this);
-};
-
-/**
- * Helper function to (un-)register IPsec kernel interfaces from plugin features.
- *
- * This function is a plugin_feature_callback_t and can be used with the
- * PLUGIN_CALLBACK macro to register an IPsec kernel interface constructor.
- *
- * @param plugin		plugin registering the kernel interface
- * @param feature		associated plugin feature
- * @param reg			TRUE to register, FALSE to unregister
- * @param data			data passed to callback, an kernel_ipsec_constructor_t
- */
-bool kernel_ipsec_register(plugin_t *plugin, plugin_feature_t *feature,
-						   bool reg, void *data);
-
-#endif /** KERNEL_IPSEC_H_ @}*/
diff --git a/src/libhydra/kernel/kernel_listener.h b/src/libhydra/kernel/kernel_listener.h
deleted file mode 100644
index 8074356..0000000
--- a/src/libhydra/kernel/kernel_listener.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2010-2013 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.
- */
-
-/**
- * @defgroup kernel_listener kernel_listener
- * @{ @ingroup hkernel
- */
-
-#ifndef KERNEL_LISTENER_H_
-#define KERNEL_LISTENER_H_
-
-typedef struct kernel_listener_t kernel_listener_t;
-
-#include <networking/host.h>
-#include <networking/tun_device.h>
-#include <selectors/traffic_selector.h>
-#include <kernel/kernel_ipsec.h>
-
-/**
- * Interface for components interested in kernel events.
- *
- * All hooks are optional.
- */
-struct kernel_listener_t {
-
-	/**
-	 * Hook called if an acquire event for a policy is received.
-	 *
-	 * @param reqid			reqid of the policy to acquire
-	 * @param src_ts		source traffic selector
-	 * @param dst_ts		destination traffic selector
-	 * @return				TRUE to remain registered, FALSE to unregister
-	 */
-	bool (*acquire)(kernel_listener_t *this, u_int32_t reqid,
-					traffic_selector_t *src_ts, traffic_selector_t *dst_ts);
-
-	/**
-	 * Hook called if an exire event for an IPsec SA is received.
-	 *
-	 * @param protocol		protocol of the expired SA
-	 * @param spi			spi of the expired SA
-	 * @param dst			destination address of expired SA
-	 * @param hard			TRUE if it is a hard expire, FALSE otherwise
-	 * @return				TRUE to remain registered, FALSE to unregister
-	 */
-	bool (*expire)(kernel_listener_t *this, u_int8_t protocol, u_int32_t spi,
-				   host_t *dst, bool hard);
-
-	/**
-	 * Hook called if the NAT mappings of an IPsec SA changed.
-	 *
-	 * @param protocol		IPsec protocol of affected SA
-	 * @param spi			spi of the SA
-	 * @param dst			old destinatino address of SA
-	 * @param remote		new remote host
-	 * @return				TRUE to remain registered, FALSE to unregister
-	 */
-	bool (*mapping)(kernel_listener_t *this, u_int8_t protocol, u_int32_t spi,
-					host_t *dst, host_t *remote);
-
-	/**
-	 * Hook called if a migrate event for a policy is received.
-	 *
-	 * @param reqid			reqid of the policy
-	 * @param src_ts		source traffic selector
-	 * @param dst_ts		destination traffic selector
-	 * @param direction		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				TRUE to remain registered, FALSE to unregister
-	 */
-	bool (*migrate)(kernel_listener_t *this, u_int32_t reqid,
-					traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-					policy_dir_t direction, host_t *local, host_t *remote);
-
-	/**
-	 * Hook called if changes in the networking layer occurred (interfaces
-	 * up/down, routes added/deleted etc.).
-	 *
-	 * @param address		TRUE if address list, FALSE if routing changed
-	 * @return				TRUE to remain registered, FALSE to unregister
-	 */
-	bool (*roam)(kernel_listener_t *this, bool address);
-
-	/**
-	 * Hook called after a TUN device was created for a virtual IP address, or
-	 * before such a device gets destroyed.
-	 *
-	 * @param tun			TUN device
-	 * @param created		TRUE if created, FALSE if going to be destroyed
-	 */
-	bool (*tun)(kernel_listener_t *this, tun_device_t *tun, bool created);
-};
-
-#endif /** KERNEL_LISTENER_H_ @}*/
diff --git a/src/libhydra/kernel/kernel_net.c b/src/libhydra/kernel/kernel_net.c
deleted file mode 100644
index 07d8b29..0000000
--- a/src/libhydra/kernel/kernel_net.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2011 Martin Willi
- * Copyright (C) 2011 revosec AG
- *
- * 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.
- */
-
-#include "kernel_net.h"
-
-#include <hydra.h>
-
-/**
- * See header
- */
-bool kernel_net_register(plugin_t *plugin, plugin_feature_t *feature,
-						 bool reg, void *data)
-{
-	if (reg)
-	{
-		return hydra->kernel_interface->add_net_interface(
-											hydra->kernel_interface,
-											(kernel_net_constructor_t)data);
-	}
-	else
-	{
-		return hydra->kernel_interface->remove_net_interface(
-											hydra->kernel_interface,
-											(kernel_net_constructor_t)data);
-	}
-}
diff --git a/src/libhydra/kernel/kernel_net.h b/src/libhydra/kernel/kernel_net.h
deleted file mode 100644
index 4312c17..0000000
--- a/src/libhydra/kernel/kernel_net.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2008-2012 Tobias Brunner
- * Copyright (C) 2007 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 kernel_net kernel_net
- * @{ @ingroup hkernel
- */
-
-#ifndef KERNEL_NET_H_
-#define KERNEL_NET_H_
-
-typedef struct kernel_net_t kernel_net_t;
-typedef enum kernel_address_type_t kernel_address_type_t;
-
-#include <collections/enumerator.h>
-#include <networking/host.h>
-#include <plugins/plugin.h>
-#include <kernel/kernel_interface.h>
-
-/**
- * Type of addresses (e.g. when enumerating them)
- */
-enum kernel_address_type_t {
-	/** normal addresses (on regular, up, non-ignored) interfaces */
-	ADDR_TYPE_REGULAR = (1 << 0),
-	/** addresses on down interfaces */
-	ADDR_TYPE_DOWN =  (1 << 1),
-	/** addresses on ignored interfaces */
-	ADDR_TYPE_IGNORED = (1 << 2),
-	/** addresses on loopback interfaces */
-	ADDR_TYPE_LOOPBACK = (1 << 3),
-	/** virtual IP addresses */
-	ADDR_TYPE_VIRTUAL = (1 << 4),
-	/** to enumerate all available addresses */
-	ADDR_TYPE_ALL = (1 << 5) - 1,
-};
-
-/**
- * Interface to the network subsystem of the kernel.
- *
- * The kernel network interface handles the communication with the kernel
- * for interface and IP address management.
- */
-struct kernel_net_t {
-
-	/**
-	 * Get the feature set supported by this kernel backend.
-	 *
-	 * @return				ORed feature-set of backend
-	 */
-	kernel_feature_t (*get_features)(kernel_net_t *this);
-
-	/**
-	 * Get our outgoing source address for a destination.
-	 *
-	 * Does a route lookup to get the source address used to reach dest.
-	 * The returned host is allocated and must be destroyed.
-	 * An optional src address can be used to check if a route is available
-	 * for the given source to dest.
-	 *
-	 * @param dest			target destination address
-	 * @param src			source address to check, or NULL
-	 * @return				outgoing source address, NULL if unreachable
-	 */
-	host_t* (*get_source_addr)(kernel_net_t *this, host_t *dest, host_t *src);
-
-	/**
-	 * Get the next hop for a destination.
-	 *
-	 * Does a route lookup to get the next hop used to reach dest.
-	 * The returned host is allocated and must be destroyed.
-	 * An optional src address can be used to check if a route is available
-	 * for the given source to dest.
-	 *
-	 * @param dest			target destination address
-	 * @param prefix		prefix length if dest is a subnet, -1 for auto
-	 * @param src			source address to check, or NULL
-	 * @return				next hop address, NULL if unreachable
-	 */
-	host_t* (*get_nexthop)(kernel_net_t *this, host_t *dest, int prefix,
-						   host_t *src);
-
-	/**
-	 * Get the interface name of a local address. Interfaces that are down or
-	 * ignored by config are not considered.
-	 *
-	 * @param host			address to get interface name from
-	 * @param name			allocated interface name (optional)
-	 * @return				TRUE if interface found and usable
-	 */
-	bool (*get_interface) (kernel_net_t *this, host_t *host, char **name);
-
-	/**
-	 * Creates an enumerator over all local addresses.
-	 *
-	 * This function blocks an internal cached address list until the
-	 * enumerator gets destroyed.
-	 * The hosts are read-only, do not modify of free.
-	 *
-	 * @param which			a combination of address types to enumerate
-	 * @return				enumerator over host_t's
-	 */
-	enumerator_t *(*create_address_enumerator) (kernel_net_t *this,
-												kernel_address_type_t which);
-
-	/**
-	 * Add a virtual IP to an interface.
-	 *
-	 * Virtual IPs are attached to an interface. If an IP is added multiple
-	 * times, the IP is refcounted and not removed until del_ip() was called
-	 * as many times as add_ip().
-	 *
-	 * @param virtual_ip	virtual ip address to assign
-	 * @param prefix		prefix length to install with IP address, -1 for auto
-	 * @param iface			interface to install virtual IP on
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*add_ip) (kernel_net_t *this, host_t *virtual_ip, int prefix,
-						char *iface);
-
-	/**
-	 * Remove a virtual IP from an interface.
-	 *
-	 * The kernel interface uses refcounting, see add_ip().
-	 *
-	 * @param virtual_ip	virtual ip address to remove
-	 * @param prefix		prefix length of the IP to uninstall, -1 for auto
-	 * @param wait			TRUE to wait until IP is gone
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*del_ip) (kernel_net_t *this, host_t *virtual_ip, int prefix,
-						bool wait);
-
-	/**
-	 * Add a route.
-	 *
-	 * @param dst_net		destination net
-	 * @param prefixlen		destination net prefix length
-	 * @param gateway		gateway for this route
-	 * @param src_ip		source ip of the route
-	 * @param if_name		name of the interface the route is bound to
-	 * @return				SUCCESS if operation completed
-	 *						ALREADY_DONE if the route already exists
-	 */
-	status_t (*add_route) (kernel_net_t *this, chunk_t dst_net,
-						   u_int8_t prefixlen, host_t *gateway, host_t *src_ip,
-						   char *if_name);
-
-	/**
-	 * Delete a route.
-	 *
-	 * @param dst_net		destination net
-	 * @param prefixlen		destination net prefix length
-	 * @param gateway		gateway for this route
-	 * @param src_ip		source ip of the route
-	 * @param if_name		name of the interface the route is bound to
-	 * @return				SUCCESS if operation completed
-	 */
-	status_t (*del_route) (kernel_net_t *this, chunk_t dst_net,
-						   u_int8_t prefixlen, host_t *gateway, host_t *src_ip,
-						   char *if_name);
-
-	/**
-	 * Destroy the implementation.
-	 */
-	void (*destroy) (kernel_net_t *this);
-};
-
-/**
- * Helper function to (un-)register net kernel interfaces from plugin features.
- *
- * This function is a plugin_feature_callback_t and can be used with the
- * PLUGIN_CALLBACK macro to register an net kernel interface constructor.
- *
- * @param plugin		plugin registering the kernel interface
- * @param feature		associated plugin feature
- * @param reg			TRUE to register, FALSE to unregister
- * @param data			data passed to callback, an kernel_net_constructor_t
- */
-bool kernel_net_register(plugin_t *plugin, plugin_feature_t *feature,
-						 bool reg, void *data);
-
-#endif /** KERNEL_NET_H_ @}*/
diff --git a/src/libhydra/plugins/kernel_netlink/Makefile.am b/src/libhydra/plugins/kernel_netlink/Makefile.am
deleted file mode 100644
index cc88554..0000000
--- a/src/libhydra/plugins/kernel_netlink/Makefile.am
+++ /dev/null
@@ -1,44 +0,0 @@
-AM_CPPFLAGS = \
-	-I${linux_headers} \
-	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
-	-DROUTING_TABLE=${routing_table} \
-	-DROUTING_TABLE_PRIO=${routing_table_prio}
-
-AM_CFLAGS = \
-	$(PLUGIN_CFLAGS)
-
-if MONOLITHIC
-noinst_LTLIBRARIES = libstrongswan-kernel-netlink.la
-else
-plugin_LTLIBRARIES = libstrongswan-kernel-netlink.la
-endif
-
-libstrongswan_kernel_netlink_la_SOURCES = \
-	kernel_netlink_plugin.h kernel_netlink_plugin.c \
-	kernel_netlink_ipsec.h kernel_netlink_ipsec.c \
-	kernel_netlink_net.h kernel_netlink_net.c \
-	kernel_netlink_shared.h kernel_netlink_shared.c
-
-libstrongswan_kernel_netlink_la_LDFLAGS = -module -avoid-version
-
-
-TESTS = tests
-
-check_PROGRAMS = $(TESTS)
-
-tests_SOURCES = \
-	tests.h tests.c \
-	suites/test_socket.c \
-	kernel_netlink_shared.c
-
-tests_CFLAGS = \
-	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libstrongswan/tests \
-	-DNETLINK_MSG_LOSS_HOOK=netlink_msg_loss \
-	@COVERAGE_CFLAGS@
-
-tests_LDFLAGS = @COVERAGE_LDFLAGS@
-tests_LDADD = \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libstrongswan/tests/libtest.la
diff --git a/src/libhydra/plugins/kernel_netlink/Makefile.in b/src/libhydra/plugins/kernel_netlink/Makefile.in
deleted file mode 100644
index 962fe1b..0000000
--- a/src/libhydra/plugins/kernel_netlink/Makefile.in
+++ /dev/null
@@ -1,1005 +0,0 @@
-# Makefile.in generated by automake 1.14.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 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.
-
- at SET_MAKE@
-
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
-  case $${target_option-} in \
-      ?) ;; \
-      *) echo "am__make_running_with_option: internal error: invalid" \
-              "target option '$${target_option-}' specified" >&2; \
-         exit 1;; \
-  esac; \
-  has_opt=no; \
-  sane_makeflags=$$MAKEFLAGS; \
-  if $(am__is_gnu_make); then \
-    sane_makeflags=$$MFLAGS; \
-  else \
-    case $$MAKEFLAGS in \
-      *\\[\ \	]*) \
-        bs=\\; \
-        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
-          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
-    esac; \
-  fi; \
-  skip_next=no; \
-  strip_trailopt () \
-  { \
-    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
-  }; \
-  for flg in $$sane_makeflags; do \
-    test $$skip_next = yes && { skip_next=no; continue; }; \
-    case $$flg in \
-      *=*|--*) continue;; \
-        -*I) strip_trailopt 'I'; skip_next=yes;; \
-      -*I?*) strip_trailopt 'I';; \
-        -*O) strip_trailopt 'O'; skip_next=yes;; \
-      -*O?*) strip_trailopt 'O';; \
-        -*l) strip_trailopt 'l'; skip_next=yes;; \
-      -*l?*) strip_trailopt 'l';; \
-      -[dEDm]) skip_next=yes;; \
-      -[JT]) skip_next=yes;; \
-    esac; \
-    case $$flg in \
-      *$$target_option*) has_opt=yes; break;; \
-    esac; \
-  done; \
-  test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@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@
-TESTS = tests$(EXEEXT)
-check_PROGRAMS = $(am__EXEEXT_1)
-subdir = src/libhydra/plugins/kernel_netlink
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
-	$(top_srcdir)/depcomp
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
-	$(top_srcdir)/m4/config/ltoptions.m4 \
-	$(top_srcdir)/m4/config/ltsugar.m4 \
-	$(top_srcdir)/m4/config/ltversion.m4 \
-	$(top_srcdir)/m4/config/lt~obsolete.m4 \
-	$(top_srcdir)/m4/macros/split-package-version.m4 \
-	$(top_srcdir)/m4/macros/with.m4 \
-	$(top_srcdir)/m4/macros/enable-disable.m4 \
-	$(top_srcdir)/m4/macros/add-plugin.m4 \
-	$(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-	$(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_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 = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
-  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
-  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
-  for p in $$list; do echo "$$p $$p"; done | \
-  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
-  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
-    if (++n[$$2] == $(am__install_max)) \
-      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
-    END { for (dir in files) print dir, files[dir] }'
-am__base_list = \
-  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
-  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__uninstall_files_from_dir = { \
-  test -z "$$files" \
-    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
-    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
-         $(am__cd) "$$dir" && rm -f $$files; }; \
-  }
-am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
-libstrongswan_kernel_netlink_la_LIBADD =
-am_libstrongswan_kernel_netlink_la_OBJECTS = kernel_netlink_plugin.lo \
-	kernel_netlink_ipsec.lo kernel_netlink_net.lo \
-	kernel_netlink_shared.lo
-libstrongswan_kernel_netlink_la_OBJECTS =  \
-	$(am_libstrongswan_kernel_netlink_la_OBJECTS)
-AM_V_lt = $(am__v_lt_ at AM_V@)
-am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 = 
-libstrongswan_kernel_netlink_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
-	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
-	$(AM_CFLAGS) $(CFLAGS) \
-	$(libstrongswan_kernel_netlink_la_LDFLAGS) $(LDFLAGS) -o $@
- at MONOLITHIC_FALSE@am_libstrongswan_kernel_netlink_la_rpath = -rpath \
- at MONOLITHIC_FALSE@	$(plugindir)
- at MONOLITHIC_TRUE@am_libstrongswan_kernel_netlink_la_rpath =
-am__EXEEXT_1 = tests$(EXEEXT)
-am__dirstamp = $(am__leading_dot)dirstamp
-am_tests_OBJECTS = tests-tests.$(OBJEXT) \
-	suites/tests-test_socket.$(OBJEXT) \
-	tests-kernel_netlink_shared.$(OBJEXT)
-tests_OBJECTS = $(am_tests_OBJECTS)
-tests_DEPENDENCIES =  \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libstrongswan/tests/libtest.la
-tests_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(tests_CFLAGS) $(CFLAGS) \
-	$(tests_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_P = $(am__v_P_ at AM_V@)
-am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_ at AM_V@)
-am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 = 
-AM_V_at = $(am__v_at_ at AM_V@)
-am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 = 
-DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-	$(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_ at AM_V@)
-am__v_CC_ = $(am__v_CC_ at AM_DEFAULT_V@)
-am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 = 
-CCLD = $(CC)
-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-	$(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_ at AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_ at AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo "  CCLD    " $@;
-am__v_CCLD_1 = 
-SOURCES = $(libstrongswan_kernel_netlink_la_SOURCES) $(tests_SOURCES)
-DIST_SOURCES = $(libstrongswan_kernel_netlink_la_SOURCES) \
-	$(tests_SOURCES)
-am__can_run_installinfo = \
-  case $$AM_UPDATE_INFO_DIR in \
-    n|no|NO) false;; \
-    *) (install-info --version) >/dev/null 2>&1;; \
-  esac
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates.  Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
-  BEGIN { nonempty = 0; } \
-  { items[$$0] = 1; nonempty = 1; } \
-  END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique.  This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
-  list='$(am__tagged_files)'; \
-  unique=`for i in $$list; do \
-    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-  done | $(am__uniquify_input)`
-ETAGS = etags
-CTAGS = ctags
-am__tty_colors_dummy = \
-  mgn= red= grn= lgn= blu= brg= std=; \
-  am__color_tests=no
-am__tty_colors = { \
-  $(am__tty_colors_dummy); \
-  if test "X$(AM_COLOR_TESTS)" = Xno; then \
-    am__color_tests=no; \
-  elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
-    am__color_tests=yes; \
-  elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
-    am__color_tests=yes; \
-  fi; \
-  if test $$am__color_tests = yes; then \
-    red=''; \
-    grn=''; \
-    lgn=''; \
-    blu=''; \
-    mgn=''; \
-    brg=''; \
-    std=''; \
-  fi; \
-}
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-ALLOCA = @ALLOCA@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BFDLIB = @BFDLIB@
-BTLIB = @BTLIB@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
-COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLIB = @DLLIB@
-DLLTOOL = @DLLTOOL@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-EASY_INSTALL = @EASY_INSTALL@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FGREP = @FGREP@
-GEM = @GEM@
-GENHTML = @GENHTML@
-GPERF = @GPERF@
-GPRBUILD = @GPRBUILD@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LCOV = @LCOV@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LEX = @LEX@
-LEXLIB = @LEXLIB@
-LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-MYSQLCFLAG = @MYSQLCFLAG@
-MYSQLCONFIG = @MYSQLCONFIG@
-MYSQLLIB = @MYSQLLIB@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OPENSSL_LIB = @OPENSSL_LIB@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
-PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
-PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
-PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PERL = @PERL@
-PKG_CONFIG = @PKG_CONFIG@
-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
-PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
-PTHREADLIB = @PTHREADLIB@
-PYTHON = @PYTHON@
-PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
-PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
-PYTHON_PLATFORM = @PYTHON_PLATFORM@
-PYTHON_PREFIX = @PYTHON_PREFIX@
-PYTHON_VERSION = @PYTHON_VERSION@
-PY_TEST = @PY_TEST@
-RANLIB = @RANLIB@
-RTLIB = @RTLIB@
-RUBY = @RUBY@
-RUBYGEMDIR = @RUBYGEMDIR@
-RUBYINCLUDE = @RUBYINCLUDE@
-RUBYLIB = @RUBYLIB@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-SOCKLIB = @SOCKLIB@
-STRIP = @STRIP@
-UNWINDLIB = @UNWINDLIB@
-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_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-aikgen_plugins = @aikgen_plugins@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-attest_plugins = @attest_plugins@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-c_plugins = @c_plugins@
-charon_natt_port = @charon_natt_port@
-charon_plugins = @charon_plugins@
-charon_udp_port = @charon_udp_port@
-clearsilver_LIBS = @clearsilver_LIBS@
-cmd_plugins = @cmd_plugins@
-datadir = @datadir@
-datarootdir = @datarootdir@
-dbusservicedir = @dbusservicedir@
-dev_headers = @dev_headers@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-fips_mode = @fips_mode@
-gtk_CFLAGS = @gtk_CFLAGS@
-gtk_LIBS = @gtk_LIBS@
-h_plugins = @h_plugins@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-imcvdir = @imcvdir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-ipsec_script = @ipsec_script@
-ipsec_script_upper = @ipsec_script_upper@
-ipsecdir = @ipsecdir@
-ipsecgroup = @ipsecgroup@
-ipseclibdir = @ipseclibdir@
-ipsecuser = @ipsecuser@
-json_CFLAGS = @json_CFLAGS@
-json_LIBS = @json_LIBS@
-libdir = @libdir@
-libexecdir = @libexecdir@
-libiptc_CFLAGS = @libiptc_CFLAGS@
-libiptc_LIBS = @libiptc_LIBS@
-linux_headers = @linux_headers@
-localedir = @localedir@
-localstatedir = @localstatedir@
-maemo_CFLAGS = @maemo_CFLAGS@
-maemo_LIBS = @maemo_LIBS@
-manager_plugins = @manager_plugins@
-mandir = @mandir@
-medsrv_plugins = @medsrv_plugins@
-mkdir_p = @mkdir_p@
-nm_CFLAGS = @nm_CFLAGS@
-nm_LIBS = @nm_LIBS@
-nm_ca_dir = @nm_ca_dir@
-nm_plugins = @nm_plugins@
-oldincludedir = @oldincludedir@
-pcsclite_CFLAGS = @pcsclite_CFLAGS@
-pcsclite_LIBS = @pcsclite_LIBS@
-pdfdir = @pdfdir@
-piddir = @piddir@
-pkgpyexecdir = @pkgpyexecdir@
-pkgpythondir = @pkgpythondir@
-pki_plugins = @pki_plugins@
-plugindir = @plugindir@
-pool_plugins = @pool_plugins@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-pyexecdir = @pyexecdir@
-pythondir = @pythondir@
-random_device = @random_device@
-resolv_conf = @resolv_conf@
-routing_table = @routing_table@
-routing_table_prio = @routing_table_prio@
-s_plugins = @s_plugins@
-sbindir = @sbindir@
-scepclient_plugins = @scepclient_plugins@
-scripts_plugins = @scripts_plugins@
-sharedstatedir = @sharedstatedir@
-soup_CFLAGS = @soup_CFLAGS@
-soup_LIBS = @soup_LIBS@
-srcdir = @srcdir@
-starter_plugins = @starter_plugins@
-strongswan_conf = @strongswan_conf@
-strongswan_options = @strongswan_options@
-swanctldir = @swanctldir@
-sysconfdir = @sysconfdir@
-systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
-systemd_daemon_LIBS = @systemd_daemon_LIBS@
-systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
-systemd_journal_LIBS = @systemd_journal_LIBS@
-systemdsystemunitdir = @systemdsystemunitdir@
-t_plugins = @t_plugins@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-urandom_device = @urandom_device@
-xml_CFLAGS = @xml_CFLAGS@
-xml_LIBS = @xml_LIBS@
-AM_CPPFLAGS = \
-	-I${linux_headers} \
-	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
-	-DROUTING_TABLE=${routing_table} \
-	-DROUTING_TABLE_PRIO=${routing_table_prio}
-
-AM_CFLAGS = \
-	$(PLUGIN_CFLAGS)
-
- at MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-kernel-netlink.la
- at MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-kernel-netlink.la
-libstrongswan_kernel_netlink_la_SOURCES = \
-	kernel_netlink_plugin.h kernel_netlink_plugin.c \
-	kernel_netlink_ipsec.h kernel_netlink_ipsec.c \
-	kernel_netlink_net.h kernel_netlink_net.c \
-	kernel_netlink_shared.h kernel_netlink_shared.c
-
-libstrongswan_kernel_netlink_la_LDFLAGS = -module -avoid-version
-tests_SOURCES = \
-	tests.h tests.c \
-	suites/test_socket.c \
-	kernel_netlink_shared.c
-
-tests_CFLAGS = \
-	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libstrongswan/tests \
-	-DNETLINK_MSG_LOSS_HOOK=netlink_msg_loss \
-	@COVERAGE_CFLAGS@
-
-tests_LDFLAGS = @COVERAGE_LDFLAGS@
-tests_LDADD = \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libstrongswan/tests/libtest.la
-
-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 ) \
-	        && { if test -f $@; then exit 0; else break; fi; }; \
-	      exit 1;; \
-	  esac; \
-	done; \
-	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libhydra/plugins/kernel_netlink/Makefile'; \
-	$(am__cd) $(top_srcdir) && \
-	  $(AUTOMAKE) --gnu src/libhydra/plugins/kernel_netlink/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
-$(am__aclocal_m4_deps):
-
-clean-noinstLTLIBRARIES:
-	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-	@list='$(noinst_LTLIBRARIES)'; \
-	locs=`for p in $$list; do echo $$p; done | \
-	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
-	      sort -u`; \
-	test -z "$$locs" || { \
-	  echo rm -f $${locs}; \
-	  rm -f $${locs}; \
-	}
-
-install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
-	@$(NORMAL_INSTALL)
-	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
-	list2=; for p in $$list; do \
-	  if test -f $$p; then \
-	    list2="$$list2 $$p"; \
-	  else :; fi; \
-	done; \
-	test -z "$$list2" || { \
-	  echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
-	  $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
-	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
-	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
-	}
-
-uninstall-pluginLTLIBRARIES:
-	@$(NORMAL_UNINSTALL)
-	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
-	for p in $$list; do \
-	  $(am__strip_dir) \
-	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
-	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
-	done
-
-clean-pluginLTLIBRARIES:
-	-test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
-	@list='$(plugin_LTLIBRARIES)'; \
-	locs=`for p in $$list; do echo $$p; done | \
-	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
-	      sort -u`; \
-	test -z "$$locs" || { \
-	  echo rm -f $${locs}; \
-	  rm -f $${locs}; \
-	}
-
-libstrongswan-kernel-netlink.la: $(libstrongswan_kernel_netlink_la_OBJECTS) $(libstrongswan_kernel_netlink_la_DEPENDENCIES) $(EXTRA_libstrongswan_kernel_netlink_la_DEPENDENCIES) 
-	$(AM_V_CCLD)$(libstrongswan_kernel_netlink_la_LINK) $(am_libstrongswan_kernel_netlink_la_rpath) $(libstrongswan_kernel_netlink_la_OBJECTS) $(libstrongswan_kernel_netlink_la_LIBADD) $(LIBS)
-
-clean-checkPROGRAMS:
-	@list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
-	echo " rm -f" $$list; \
-	rm -f $$list || exit $$?; \
-	test -n "$(EXEEXT)" || exit 0; \
-	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
-	echo " rm -f" $$list; \
-	rm -f $$list
-suites/$(am__dirstamp):
-	@$(MKDIR_P) suites
-	@: > suites/$(am__dirstamp)
-suites/$(DEPDIR)/$(am__dirstamp):
-	@$(MKDIR_P) suites/$(DEPDIR)
-	@: > suites/$(DEPDIR)/$(am__dirstamp)
-suites/tests-test_socket.$(OBJEXT): suites/$(am__dirstamp) \
-	suites/$(DEPDIR)/$(am__dirstamp)
-
-tests$(EXEEXT): $(tests_OBJECTS) $(tests_DEPENDENCIES) $(EXTRA_tests_DEPENDENCIES) 
-	@rm -f tests$(EXEEXT)
-	$(AM_V_CCLD)$(tests_LINK) $(tests_OBJECTS) $(tests_LDADD) $(LIBS)
-
-mostlyclean-compile:
-	-rm -f *.$(OBJEXT)
-	-rm -f suites/*.$(OBJEXT)
-
-distclean-compile:
-	-rm -f *.tab.c
-
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_netlink_ipsec.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_netlink_net.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_netlink_plugin.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_netlink_shared.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/tests-kernel_netlink_shared.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/tests-tests.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/tests-test_socket.Po at am__quote@
-
-.c.o:
- at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
- at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
- at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ $<
-
-.c.obj:
- at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
- at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
- at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-
-.c.lo:
- at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
- at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
- at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LTCOMPILE) -c -o $@ $<
-
-tests-tests.o: tests.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT tests-tests.o -MD -MP -MF $(DEPDIR)/tests-tests.Tpo -c -o tests-tests.o `test -f 'tests.c' || echo '$(srcdir)/'`tests.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/tests-tests.Tpo $(DEPDIR)/tests-tests.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='tests.c' object='tests-tests.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o tests-tests.o `test -f 'tests.c' || echo '$(srcdir)/'`tests.c
-
-tests-tests.obj: tests.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT tests-tests.obj -MD -MP -MF $(DEPDIR)/tests-tests.Tpo -c -o tests-tests.obj `if test -f 'tests.c'; then $(CYGPATH_W) 'tests.c'; else $(CYGPATH_W) '$(srcdir)/tests.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/tests-tests.Tpo $(DEPDIR)/tests-tests.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='tests.c' object='tests-tests.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o tests-tests.obj `if test -f 'tests.c'; then $(CYGPATH_W) 'tests.c'; else $(CYGPATH_W) '$(srcdir)/tests.c'; fi`
-
-suites/tests-test_socket.o: suites/test_socket.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT suites/tests-test_socket.o -MD -MP -MF suites/$(DEPDIR)/tests-test_socket.Tpo -c -o suites/tests-test_socket.o `test -f 'suites/test_socket.c' || echo '$(srcdir)/'`suites/test_socket.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/tests-test_socket.Tpo suites/$(DEPDIR)/tests-test_socket.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_socket.c' object='suites/tests-test_socket.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o suites/tests-test_socket.o `test -f 'suites/test_socket.c' || echo '$(srcdir)/'`suites/test_socket.c
-
-suites/tests-test_socket.obj: suites/test_socket.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT suites/tests-test_socket.obj -MD -MP -MF suites/$(DEPDIR)/tests-test_socket.Tpo -c -o suites/tests-test_socket.obj `if test -f 'suites/test_socket.c'; then $(CYGPATH_W) 'suites/test_socket.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_socket.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/tests-test_socket.Tpo suites/$(DEPDIR)/tests-test_socket.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_socket.c' object='suites/tests-test_socket.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o suites/tests-test_socket.obj `if test -f 'suites/test_socket.c'; then $(CYGPATH_W) 'suites/test_socket.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_socket.c'; fi`
-
-tests-kernel_netlink_shared.o: kernel_netlink_shared.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT tests-kernel_netlink_shared.o -MD -MP -MF $(DEPDIR)/tests-kernel_netlink_shared.Tpo -c -o tests-kernel_netlink_shared.o `test -f 'kernel_netlink_shared.c' || echo '$(srcdir)/'`kernel_netlink_shared.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/tests-kernel_netlink_shared.Tpo $(DEPDIR)/tests-kernel_netlink_shared.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='kernel_netlink_shared.c' object='tests-kernel_netlink_shared.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o tests-kernel_netlink_shared.o `test -f 'kernel_netlink_shared.c' || echo '$(srcdir)/'`kernel_netlink_shared.c
-
-tests-kernel_netlink_shared.obj: kernel_netlink_shared.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT tests-kernel_netlink_shared.obj -MD -MP -MF $(DEPDIR)/tests-kernel_netlink_shared.Tpo -c -o tests-kernel_netlink_shared.obj `if test -f 'kernel_netlink_shared.c'; then $(CYGPATH_W) 'kernel_netlink_shared.c'; else $(CYGPATH_W) '$(srcdir)/kernel_netlink_shared.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/tests-kernel_netlink_shared.Tpo $(DEPDIR)/tests-kernel_netlink_shared.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='kernel_netlink_shared.c' object='tests-kernel_netlink_shared.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o tests-kernel_netlink_shared.obj `if test -f 'kernel_netlink_shared.c'; then $(CYGPATH_W) 'kernel_netlink_shared.c'; else $(CYGPATH_W) '$(srcdir)/kernel_netlink_shared.c'; fi`
-
-mostlyclean-libtool:
-	-rm -f *.lo
-
-clean-libtool:
-	-rm -rf .libs _libs
-
-ID: $(am__tagged_files)
-	$(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-am
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-	set x; \
-	here=`pwd`; \
-	$(am__define_uniq_tagged_files); \
-	shift; \
-	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-	  test -n "$$unique" || unique=$$empty_fix; \
-	  if test $$# -gt 0; then \
-	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-	      "$$@" $$unique; \
-	  else \
-	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-	      $$unique; \
-	  fi; \
-	fi
-ctags: ctags-am
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-	$(am__define_uniq_tagged_files); \
-	test -z "$(CTAGS_ARGS)$$unique" \
-	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-	     $$unique
-
-GTAGS:
-	here=`$(am__cd) $(top_builddir) && pwd` \
-	  && $(am__cd) $(top_srcdir) \
-	  && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-am
-
-cscopelist-am: $(am__tagged_files)
-	list='$(am__tagged_files)'; \
-	case "$(srcdir)" in \
-	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
-	  *) sdir=$(subdir)/$(srcdir) ;; \
-	esac; \
-	for i in $$list; do \
-	  if test -f "$$i"; then \
-	    echo "$(subdir)/$$i"; \
-	  else \
-	    echo "$$sdir/$$i"; \
-	  fi; \
-	done >> $(top_builddir)/cscope.files
-
-distclean-tags:
-	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-check-TESTS: $(TESTS)
-	@failed=0; all=0; xfail=0; xpass=0; skip=0; \
-	srcdir=$(srcdir); export srcdir; \
-	list=' $(TESTS) '; \
-	$(am__tty_colors); \
-	if test -n "$$list"; then \
-	  for tst in $$list; do \
-	    if test -f ./$$tst; then dir=./; \
-	    elif test -f $$tst; then dir=; \
-	    else dir="$(srcdir)/"; fi; \
-	    if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
-	      all=`expr $$all + 1`; \
-	      case " $(XFAIL_TESTS) " in \
-	      *[\ \	]$$tst[\ \	]*) \
-		xpass=`expr $$xpass + 1`; \
-		failed=`expr $$failed + 1`; \
-		col=$$red; res=XPASS; \
-	      ;; \
-	      *) \
-		col=$$grn; res=PASS; \
-	      ;; \
-	      esac; \
-	    elif test $$? -ne 77; then \
-	      all=`expr $$all + 1`; \
-	      case " $(XFAIL_TESTS) " in \
-	      *[\ \	]$$tst[\ \	]*) \
-		xfail=`expr $$xfail + 1`; \
-		col=$$lgn; res=XFAIL; \
-	      ;; \
-	      *) \
-		failed=`expr $$failed + 1`; \
-		col=$$red; res=FAIL; \
-	      ;; \
-	      esac; \
-	    else \
-	      skip=`expr $$skip + 1`; \
-	      col=$$blu; res=SKIP; \
-	    fi; \
-	    echo "$${col}$$res$${std}: $$tst"; \
-	  done; \
-	  if test "$$all" -eq 1; then \
-	    tests="test"; \
-	    All=""; \
-	  else \
-	    tests="tests"; \
-	    All="All "; \
-	  fi; \
-	  if test "$$failed" -eq 0; then \
-	    if test "$$xfail" -eq 0; then \
-	      banner="$$All$$all $$tests passed"; \
-	    else \
-	      if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
-	      banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
-	    fi; \
-	  else \
-	    if test "$$xpass" -eq 0; then \
-	      banner="$$failed of $$all $$tests failed"; \
-	    else \
-	      if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
-	      banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
-	    fi; \
-	  fi; \
-	  dashes="$$banner"; \
-	  skipped=""; \
-	  if test "$$skip" -ne 0; then \
-	    if test "$$skip" -eq 1; then \
-	      skipped="($$skip test was not run)"; \
-	    else \
-	      skipped="($$skip tests were not run)"; \
-	    fi; \
-	    test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
-	      dashes="$$skipped"; \
-	  fi; \
-	  report=""; \
-	  if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
-	    report="Please report to $(PACKAGE_BUGREPORT)"; \
-	    test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
-	      dashes="$$report"; \
-	  fi; \
-	  dashes=`echo "$$dashes" | sed s/./=/g`; \
-	  if test "$$failed" -eq 0; then \
-	    col="$$grn"; \
-	  else \
-	    col="$$red"; \
-	  fi; \
-	  echo "$${col}$$dashes$${std}"; \
-	  echo "$${col}$$banner$${std}"; \
-	  test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
-	  test -z "$$report" || echo "$${col}$$report$${std}"; \
-	  echo "$${col}$$dashes$${std}"; \
-	  test "$$failed" -eq 0; \
-	else :; fi
-
-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 "$(distdir)/$$file"; then \
-	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-	    fi; \
-	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-	    fi; \
-	    cp -fpR $$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
-	$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
-	$(MAKE) $(AM_MAKEFLAGS) check-TESTS
-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:
-	if test -z '$(STRIP)'; then \
-	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-	      install; \
-	else \
-	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-	fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
-	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-	-rm -f suites/$(DEPDIR)/$(am__dirstamp)
-	-rm -f suites/$(am__dirstamp)
-
-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-checkPROGRAMS clean-generic clean-libtool \
-	clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES mostlyclean-am
-
-distclean: distclean-am
-	-rm -rf ./$(DEPDIR) suites/$(DEPDIR)
-	-rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
-	distclean-tags
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am: install-pluginLTLIBRARIES
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
-	-rm -rf ./$(DEPDIR) suites/$(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: check-am install-am install-strip
-
-.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \
-	clean-checkPROGRAMS clean-generic clean-libtool \
-	clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES cscopelist-am \
-	ctags ctags-am 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 tags-am 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/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
deleted file mode 100644
index 8c506d9..0000000
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ /dev/null
@@ -1,2966 +0,0 @@
-/*
- * Copyright (C) 2006-2015 Tobias Brunner
- * Copyright (C) 2005-2009 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
- * 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.
- */
-
-#include <sys/types.h>
-#include <sys/socket.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 <unistd.h>
-#include <time.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-
-#include "kernel_netlink_ipsec.h"
-#include "kernel_netlink_shared.h"
-
-#include <hydra.h>
-#include <utils/debug.h>
-#include <threading/mutex.h>
-#include <collections/array.h>
-#include <collections/hashtable.h>
-#include <collections/linked_list.h>
-
-/** Required for Linux 2.6.26 kernel and later */
-#ifndef XFRM_STATE_AF_UNSPEC
-#define XFRM_STATE_AF_UNSPEC 32
-#endif
-
-/** From linux/in.h */
-#ifndef IP_XFRM_POLICY
-#define IP_XFRM_POLICY 17
-#endif
-
-/** Missing on uclibc */
-#ifndef IPV6_XFRM_POLICY
-#define IPV6_XFRM_POLICY 34
-#endif /*IPV6_XFRM_POLICY*/
-
-/* from linux/udp.h */
-#ifndef UDP_ENCAP
-#define UDP_ENCAP 100
-#endif
-
-#ifndef UDP_ENCAP_ESPINUDP
-#define UDP_ENCAP_ESPINUDP 2
-#endif
-
-/* this is not defined on some platforms */
-#ifndef SOL_UDP
-#define SOL_UDP IPPROTO_UDP
-#endif
-
-/** Base priority for installed policies */
-#define PRIO_BASE 384
-
-/** Default lifetime of an acquire XFRM state (in seconds) */
-#define DEFAULT_ACQUIRE_LIFETIME 165
-
-/**
- * Map the limit for bytes and packets to XFRM_INF by default
- */
-#define XFRM_LIMIT(x) ((x) == 0 ? XFRM_INF : (x))
-
-/**
- * Create ORable bitfield of XFRM NL groups
- */
-#define XFRMNLGRP(x) (1<<(XFRMNLGRP_##x-1))
-
-/**
- * Returns a pointer to the first rtattr following the nlmsghdr *nlh and the
- * 'usual' netlink data x like 'struct xfrm_usersa_info'
- */
-#define XFRM_RTA(nlh, x) ((struct rtattr*)(NLMSG_DATA(nlh) + \
-										   NLMSG_ALIGN(sizeof(x))))
-/**
- * Returns the total size of attached rta data
- * (after 'usual' netlink data x like 'struct xfrm_usersa_info')
- */
-#define XFRM_PAYLOAD(nlh, x) NLMSG_PAYLOAD(nlh, sizeof(x))
-
-typedef struct kernel_algorithm_t kernel_algorithm_t;
-
-/**
- * Mapping of IKEv2 kernel identifier to linux crypto API names
- */
-struct kernel_algorithm_t {
-	/**
-	 * Identifier specified in IKEv2
-	 */
-	int ikev2;
-
-	/**
-	 * Name of the algorithm in linux crypto API
-	 */
-	char *name;
-};
-
-ENUM(xfrm_msg_names, XFRM_MSG_NEWSA, XFRM_MSG_MAPPING,
-	"XFRM_MSG_NEWSA",
-	"XFRM_MSG_DELSA",
-	"XFRM_MSG_GETSA",
-	"XFRM_MSG_NEWPOLICY",
-	"XFRM_MSG_DELPOLICY",
-	"XFRM_MSG_GETPOLICY",
-	"XFRM_MSG_ALLOCSPI",
-	"XFRM_MSG_ACQUIRE",
-	"XFRM_MSG_EXPIRE",
-	"XFRM_MSG_UPDPOLICY",
-	"XFRM_MSG_UPDSA",
-	"XFRM_MSG_POLEXPIRE",
-	"XFRM_MSG_FLUSHSA",
-	"XFRM_MSG_FLUSHPOLICY",
-	"XFRM_MSG_NEWAE",
-	"XFRM_MSG_GETAE",
-	"XFRM_MSG_REPORT",
-	"XFRM_MSG_MIGRATE",
-	"XFRM_MSG_NEWSADINFO",
-	"XFRM_MSG_GETSADINFO",
-	"XFRM_MSG_NEWSPDINFO",
-	"XFRM_MSG_GETSPDINFO",
-	"XFRM_MSG_MAPPING"
-);
-
-ENUM(xfrm_attr_type_names, XFRMA_UNSPEC, XFRMA_REPLAY_ESN_VAL,
-	"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",
-	"XFRMA_ALG_AUTH_TRUNC",
-	"XFRMA_MARK",
-	"XFRMA_TFCPAD",
-	"XFRMA_REPLAY_ESN_VAL",
-);
-
-/**
- * Algorithms for encryption
- */
-static kernel_algorithm_t encryption_algs[] = {
-/*	{ENCR_DES_IV64,				"***"				}, */
-	{ENCR_DES,					"des"				},
-	{ENCR_3DES,					"des3_ede"			},
-/*	{ENCR_RC5,					"***"				}, */
-/*	{ENCR_IDEA,					"***"				}, */
-	{ENCR_CAST,					"cast5"				},
-	{ENCR_BLOWFISH,				"blowfish"			},
-/*	{ENCR_3IDEA,				"***"				}, */
-/*	{ENCR_DES_IV32,				"***"				}, */
-	{ENCR_NULL,					"cipher_null"		},
-	{ENCR_AES_CBC,				"aes"				},
-	{ENCR_AES_CTR,				"rfc3686(ctr(aes))"	},
-	{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))"	},
-	{ENCR_NULL_AUTH_AES_GMAC,	"rfc4543(gcm(aes))"	},
-	{ENCR_CAMELLIA_CBC,			"cbc(camellia)"		},
-/*	{ENCR_CAMELLIA_CTR,			"***"				}, */
-/*	{ENCR_CAMELLIA_CCM_ICV8,	"***"				}, */
-/*	{ENCR_CAMELLIA_CCM_ICV12,	"***"				}, */
-/*	{ENCR_CAMELLIA_CCM_ICV16,	"***"				}, */
-	{ENCR_SERPENT_CBC,			"serpent"			},
-	{ENCR_TWOFISH_CBC,			"twofish"			},
-	{ENCR_CHACHA20_POLY1305,	"rfc7539esp(chacha20,poly1305)"},
-};
-
-/**
- * Algorithms for integrity protection
- */
-static kernel_algorithm_t integrity_algs[] = {
-	{AUTH_HMAC_MD5_96,			"md5"				},
-	{AUTH_HMAC_MD5_128,			"hmac(md5)"			},
-	{AUTH_HMAC_SHA1_96,			"sha1"				},
-	{AUTH_HMAC_SHA1_160,		"hmac(sha1)"		},
-	{AUTH_HMAC_SHA2_256_96,		"sha256"			},
-	{AUTH_HMAC_SHA2_256_128,	"hmac(sha256)"		},
-	{AUTH_HMAC_SHA2_384_192,	"hmac(sha384)"		},
-	{AUTH_HMAC_SHA2_512_256,	"hmac(sha512)"		},
-/*	{AUTH_DES_MAC,				"***"				}, */
-/*	{AUTH_KPDK_MD5,				"***"				}, */
-	{AUTH_AES_XCBC_96,			"xcbc(aes)"			},
-};
-
-/**
- * Algorithms for IPComp
- */
-static kernel_algorithm_t compression_algs[] = {
-/*	{IPCOMP_OUI,				"***"				}, */
-	{IPCOMP_DEFLATE,			"deflate"			},
-	{IPCOMP_LZS,				"lzs"				},
-	{IPCOMP_LZJH,				"lzjh"				},
-};
-
-/**
- * Look up a kernel algorithm name and its key size
- */
-static char* lookup_algorithm(transform_type_t type, int ikev2)
-{
-	kernel_algorithm_t *list;
-	int i, count;
-	char *name;
-
-	switch (type)
-	{
-		case ENCRYPTION_ALGORITHM:
-			list = encryption_algs;
-			count = countof(encryption_algs);
-			break;
-		case INTEGRITY_ALGORITHM:
-			list = integrity_algs;
-			count = countof(integrity_algs);
-			break;
-		case COMPRESSION_ALGORITHM:
-			list = compression_algs;
-			count = countof(compression_algs);
-			break;
-		default:
-			return NULL;
-	}
-	for (i = 0; i < count; i++)
-	{
-		if (list[i].ikev2 == ikev2)
-		{
-			return list[i].name;
-		}
-	}
-	if (hydra->kernel_interface->lookup_algorithm(hydra->kernel_interface,
-												  ikev2, type, NULL, &name))
-	{
-		return name;
-	}
-	return NULL;
-}
-
-typedef struct private_kernel_netlink_ipsec_t private_kernel_netlink_ipsec_t;
-
-/**
- * Private variables and functions of kernel_netlink class.
- */
-struct private_kernel_netlink_ipsec_t {
-	/**
-	 * Public part of the kernel_netlink_t object
-	 */
-	kernel_netlink_ipsec_t public;
-
-	/**
-	 * Mutex to lock access to installed policies
-	 */
-	mutex_t *mutex;
-
-	/**
-	 * Hash table of installed policies (policy_entry_t)
-	 */
-	hashtable_t *policies;
-
-	/**
-	 * Hash table of IPsec SAs using policies (ipsec_sa_t)
-	 */
-	hashtable_t *sas;
-
-	/**
-	 * Netlink xfrm socket (IPsec)
-	 */
-	netlink_socket_t *socket_xfrm;
-
-	/**
-	 * Netlink xfrm socket to receive acquire and expire events
-	 */
-	int socket_xfrm_events;
-
-	/**
-	 * Whether to install routes along policies
-	 */
-	bool install_routes;
-
-	/**
-	 * Whether to set protocol and ports on selector installed with transport
-	 * mode IPsec SAs
-	 */
-	bool proto_port_transport;
-
-	/**
-	 * Whether to always use UPDATE to install policies
-	 */
-	bool policy_update;
-
-	/**
-	 * Installed port based IKE bypass policies, as bypass_t
-	 */
-	array_t *bypass;
-};
-
-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 a route_entry_t object
- */
-static void route_entry_destroy(route_entry_t *this)
-{
-	free(this->if_name);
-	this->src_ip->destroy(this->src_ip);
-	DESTROY_IF(this->gateway);
-	chunk_free(&this->dst_net);
-	free(this);
-}
-
-/**
- * Compare two route_entry_t objects
- */
-static bool route_entry_equals(route_entry_t *a, route_entry_t *b)
-{
-	return a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
-		   a->src_ip->ip_equals(a->src_ip, b->src_ip) &&
-		   a->gateway->ip_equals(a->gateway, b->gateway) &&
-		   chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen;
-}
-
-typedef struct ipsec_sa_t ipsec_sa_t;
-
-/**
- * IPsec SA assigned to a policy.
- */
-struct ipsec_sa_t {
-	/** Source address of this SA */
-	host_t *src;
-
-	/** Destination address of this SA */
-	host_t *dst;
-
-	/** Optional mark */
-	mark_t mark;
-
-	/** Description of this SA */
-	ipsec_sa_cfg_t cfg;
-
-	/** Reference count for this SA */
-	refcount_t refcount;
-};
-
-/**
- * Hash function for ipsec_sa_t objects
- */
-static u_int ipsec_sa_hash(ipsec_sa_t *sa)
-{
-	return chunk_hash_inc(sa->src->get_address(sa->src),
-						  chunk_hash_inc(sa->dst->get_address(sa->dst),
-						  chunk_hash_inc(chunk_from_thing(sa->mark),
-						  chunk_hash(chunk_from_thing(sa->cfg)))));
-}
-
-/**
- * Equality function for ipsec_sa_t objects
- */
-static bool ipsec_sa_equals(ipsec_sa_t *sa, ipsec_sa_t *other_sa)
-{
-	return sa->src->ip_equals(sa->src, other_sa->src) &&
-		   sa->dst->ip_equals(sa->dst, other_sa->dst) &&
-		   memeq(&sa->mark, &other_sa->mark, sizeof(mark_t)) &&
-		   memeq(&sa->cfg, &other_sa->cfg, sizeof(ipsec_sa_cfg_t));
-}
-
-/**
- * Allocate or reference an IPsec SA object
- */
-static ipsec_sa_t *ipsec_sa_create(private_kernel_netlink_ipsec_t *this,
-								   host_t *src, host_t *dst, mark_t mark,
-								   ipsec_sa_cfg_t *cfg)
-{
-	ipsec_sa_t *sa, *found;
-	INIT(sa,
-		.src = src,
-		.dst = dst,
-		.mark = mark,
-		.cfg = *cfg,
-	);
-	found = this->sas->get(this->sas, sa);
-	if (!found)
-	{
-		sa->src = src->clone(src);
-		sa->dst = dst->clone(dst);
-		this->sas->put(this->sas, sa, sa);
-	}
-	else
-	{
-		free(sa);
-		sa = found;
-	}
-	ref_get(&sa->refcount);
-	return sa;
-}
-
-/**
- * Release and destroy an IPsec SA object
- */
-static void ipsec_sa_destroy(private_kernel_netlink_ipsec_t *this,
-							 ipsec_sa_t *sa)
-{
-	if (ref_put(&sa->refcount))
-	{
-		this->sas->remove(this->sas, sa);
-		DESTROY_IF(sa->src);
-		DESTROY_IF(sa->dst);
-		free(sa);
-	}
-}
-
-typedef struct policy_sa_t policy_sa_t;
-typedef struct policy_sa_fwd_t policy_sa_fwd_t;
-
-/**
- * Mapping between a policy and an IPsec SA.
- */
-struct policy_sa_t {
-	/** Priority assigned to the policy when installed with this SA */
-	u_int32_t priority;
-
-	/** Type of the policy */
-	policy_type_t type;
-
-	/** Assigned SA */
-	ipsec_sa_t *sa;
-};
-
-/**
- * For forward policies we also cache the traffic selectors in order to install
- * the route.
- */
-struct policy_sa_fwd_t {
-	/** Generic interface */
-	policy_sa_t generic;
-
-	/** Source traffic selector of this policy */
-	traffic_selector_t *src_ts;
-
-	/** Destination traffic selector of this policy */
-	traffic_selector_t *dst_ts;
-};
-
-/**
- * Create a policy_sa(_fwd)_t object
- */
-static policy_sa_t *policy_sa_create(private_kernel_netlink_ipsec_t *this,
-	policy_dir_t dir, policy_type_t type, host_t *src, host_t *dst,
-	traffic_selector_t *src_ts, traffic_selector_t *dst_ts, mark_t mark,
-	ipsec_sa_cfg_t *cfg)
-{
-	policy_sa_t *policy;
-
-	if (dir == POLICY_FWD)
-	{
-		policy_sa_fwd_t *fwd;
-		INIT(fwd,
-			.src_ts = src_ts->clone(src_ts),
-			.dst_ts = dst_ts->clone(dst_ts),
-		);
-		policy = &fwd->generic;
-	}
-	else
-	{
-		INIT(policy, .priority = 0);
-	}
-	policy->type = type;
-	policy->sa = ipsec_sa_create(this, src, dst, mark, cfg);
-	return policy;
-}
-
-/**
- * Destroy a policy_sa(_fwd)_t object
- */
-static void policy_sa_destroy(policy_sa_t *policy, policy_dir_t *dir,
-							  private_kernel_netlink_ipsec_t *this)
-{
-	if (*dir == POLICY_FWD)
-	{
-		policy_sa_fwd_t *fwd = (policy_sa_fwd_t*)policy;
-		fwd->src_ts->destroy(fwd->src_ts);
-		fwd->dst_ts->destroy(fwd->dst_ts);
-	}
-	ipsec_sa_destroy(this, policy->sa);
-	free(policy);
-}
-
-typedef struct policy_entry_t policy_entry_t;
-
-/**
- * Installed kernel policy.
- */
-struct policy_entry_t {
-
-	/** Direction of this policy: in, out, forward */
-	u_int8_t direction;
-
-	/** Parameters of installed policy */
-	struct xfrm_selector sel;
-
-	/** Optional mark */
-	u_int32_t mark;
-
-	/** Associated route installed for this policy */
-	route_entry_t *route;
-
-	/** List of SAs this policy is used by, ordered by priority */
-	linked_list_t *used_by;
-
-	/** reqid for this policy */
-	u_int32_t reqid;
-};
-
-/**
- * Destroy a policy_entry_t object
- */
-static void policy_entry_destroy(private_kernel_netlink_ipsec_t *this,
-								 policy_entry_t *policy)
-{
-	if (policy->route)
-	{
-		route_entry_destroy(policy->route);
-	}
-	if (policy->used_by)
-	{
-		policy->used_by->invoke_function(policy->used_by,
-										(linked_list_invoke_t)policy_sa_destroy,
-										 &policy->direction, this);
-		policy->used_by->destroy(policy->used_by);
-	}
-	free(policy);
-}
-
-/**
- * Hash function for policy_entry_t objects
- */
-static u_int policy_hash(policy_entry_t *key)
-{
-	chunk_t chunk = chunk_from_thing(key->sel);
-	return chunk_hash_inc(chunk, chunk_hash(chunk_from_thing(key->mark)));
-}
-
-/**
- * Equality function for policy_entry_t objects
- */
-static bool policy_equals(policy_entry_t *key, policy_entry_t *other_key)
-{
-	return memeq(&key->sel, &other_key->sel, sizeof(struct xfrm_selector)) &&
-		   key->mark == other_key->mark &&
-		   key->direction == other_key->direction;
-}
-
-/**
- * Calculate the priority of a policy
- */
-static inline u_int32_t get_priority(policy_entry_t *policy,
-									 policy_priority_t prio)
-{
-	u_int32_t priority = PRIO_BASE;
-	switch (prio)
-	{
-		case POLICY_PRIORITY_FALLBACK:
-			priority <<= 1;
-			/* fall-through */
-		case POLICY_PRIORITY_ROUTED:
-			priority <<= 1;
-			/* fall-through */
-		case POLICY_PRIORITY_DEFAULT:
-			priority <<= 1;
-			/* fall-through */
-		case POLICY_PRIORITY_PASS:
-			break;
-	}
-	/* calculate priority based on selector size, small size = high prio */
-	priority -= policy->sel.prefixlen_s;
-	priority -= policy->sel.prefixlen_d;
-	priority <<= 2; /* make some room for the two flags */
-	priority += policy->sel.sport_mask || policy->sel.dport_mask ? 0 : 2;
-	priority += policy->sel.proto ? 0 : 1;
-	return priority;
-}
-
-/**
- * Convert the general ipsec mode to the one defined in xfrm.h
- */
-static u_int8_t mode2kernel(ipsec_mode_t mode)
-{
-	switch (mode)
-	{
-		case MODE_TRANSPORT:
-			return XFRM_MODE_TRANSPORT;
-		case MODE_TUNNEL:
-			return XFRM_MODE_TUNNEL;
-		case MODE_BEET:
-			return XFRM_MODE_BEET;
-		default:
-			return mode;
-	}
-}
-
-/**
- * Convert a host_t to a struct xfrm_address
- */
-static void host2xfrm(host_t *host, xfrm_address_t *xfrm)
-{
-	chunk_t chunk = host->get_address(host);
-	memcpy(xfrm, chunk.ptr, min(chunk.len, sizeof(xfrm_address_t)));
-}
-
-/**
- * Convert a struct xfrm_address to a host_t
- */
-static host_t* xfrm2host(int family, xfrm_address_t *xfrm, u_int16_t port)
-{
-	chunk_t chunk;
-
-	switch (family)
-	{
-		case AF_INET:
-			chunk = chunk_create((u_char*)&xfrm->a4, sizeof(xfrm->a4));
-			break;
-		case AF_INET6:
-			chunk = chunk_create((u_char*)&xfrm->a6, sizeof(xfrm->a6));
-			break;
-		default:
-			return NULL;
-	}
-	return host_create_from_chunk(family, chunk, ntohs(port));
-}
-
-/**
- * Convert a traffic selector address range to subnet and its mask.
- */
-static void ts2subnet(traffic_selector_t* ts,
-					  xfrm_address_t *net, u_int8_t *mask)
-{
-	host_t *net_host;
-	chunk_t net_chunk;
-
-	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);
-}
-
-/**
- * Convert a traffic selector port range to port/portmask
- */
-static void ts2ports(traffic_selector_t* ts,
-					 u_int16_t *port, u_int16_t *mask)
-{
-	/* Linux does not seem to accept complex portmasks. Only
-	 * any or a specific port is allowed. We set to any, if we have
-	 * a port range, or to a specific, if we have one port only.
-	 */
-	u_int16_t from, to;
-
-	from = ts->get_from_port(ts);
-	to = ts->get_to_port(ts);
-
-	if (from == to)
-	{
-		*port = htons(from);
-		*mask = ~0;
-	}
-	else
-	{
-		*port = 0;
-		*mask = 0;
-	}
-}
-
-/**
- * Convert a pair of traffic_selectors to an xfrm_selector
- */
-static struct xfrm_selector ts2selector(traffic_selector_t *src,
-										traffic_selector_t *dst)
-{
-	struct xfrm_selector sel;
-	u_int16_t port;
-
-	memset(&sel, 0, sizeof(sel));
-	sel.family = (src->get_type(src) == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6;
-	/* src or dest proto may be "any" (0), use more restrictive one */
-	sel.proto = max(src->get_protocol(src), dst->get_protocol(dst));
-	ts2subnet(dst, &sel.daddr, &sel.prefixlen_d);
-	ts2subnet(src, &sel.saddr, &sel.prefixlen_s);
-	ts2ports(dst, &sel.dport, &sel.dport_mask);
-	ts2ports(src, &sel.sport, &sel.sport_mask);
-	if ((sel.proto == IPPROTO_ICMP || sel.proto == IPPROTO_ICMPV6) &&
-		(sel.dport || sel.sport))
-	{
-		/* the kernel expects the ICMP type and code in the source and
-		 * destination port fields, respectively. */
-		port = ntohs(max(sel.dport, sel.sport));
-		sel.sport = htons(traffic_selector_icmp_type(port));
-		sel.sport_mask = sel.sport ? ~0 : 0;
-		sel.dport = htons(traffic_selector_icmp_code(port));
-		sel.dport_mask = sel.dport ? ~0 : 0;
-	}
-	sel.ifindex = 0;
-	sel.user = 0;
-
-	return sel;
-}
-
-/**
- * Convert an xfrm_selector to a src|dst traffic_selector
- */
-static traffic_selector_t* selector2ts(struct xfrm_selector *sel, bool src)
-{
-	u_char *addr;
-	u_int8_t prefixlen;
-	u_int16_t port = 0;
-	host_t *host = NULL;
-
-	if (src)
-	{
-		addr = (u_char*)&sel->saddr;
-		prefixlen = sel->prefixlen_s;
-		if (sel->sport_mask)
-		{
-			port = ntohs(sel->sport);
-		}
-	}
-	else
-	{
-		addr = (u_char*)&sel->daddr;
-		prefixlen = sel->prefixlen_d;
-		if (sel->dport_mask)
-		{
-			port = ntohs(sel->dport);
-		}
-	}
-	if (sel->proto == IPPROTO_ICMP || sel->proto == IPPROTO_ICMPV6)
-	{	/* convert ICMP[v6] message type and code as supplied by the kernel in
-		 * source and destination ports (both in network order) */
-		port = (sel->sport >> 8) | (sel->dport & 0xff00);
-		port = ntohs(port);
-	}
-	/* 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)
-	{
-		host = host_create_from_chunk(AF_INET, chunk_create(addr, 4), 0);
-	}
-	else if (sel->family == AF_INET6 || sel->prefixlen_s == 128)
-	{
-		host = host_create_from_chunk(AF_INET6, chunk_create(addr, 16), 0);
-	}
-
-	if (host)
-	{
-		return traffic_selector_create_from_subnet(host, prefixlen,
-											sel->proto, port, port ?: 65535);
-	}
-	return NULL;
-}
-
-/**
- * Process a XFRM_MSG_ACQUIRE from kernel
- */
-static void process_acquire(private_kernel_netlink_ipsec_t *this,
-							struct nlmsghdr *hdr)
-{
-	struct xfrm_user_acquire *acquire;
-	struct rtattr *rta;
-	size_t rtasize;
-	traffic_selector_t *src_ts, *dst_ts;
-	u_int32_t reqid = 0;
-	int proto = 0;
-
-	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))
-	{
-		DBG2(DBG_KNL, "  %N", xfrm_attr_type_names, rta->rta_type);
-
-		if (rta->rta_type == XFRMA_TMPL)
-		{
-			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)
-	{
-		case 0:
-		case IPPROTO_ESP:
-		case IPPROTO_AH:
-			break;
-		default:
-			/* acquire for AH/ESP only, not for IPCOMP */
-			return;
-	}
-	src_ts = selector2ts(&acquire->sel, TRUE);
-	dst_ts = selector2ts(&acquire->sel, FALSE);
-
-	hydra->kernel_interface->acquire(hydra->kernel_interface, reqid, src_ts,
-									 dst_ts);
-}
-
-/**
- * Process a XFRM_MSG_EXPIRE from kernel
- */
-static void process_expire(private_kernel_netlink_ipsec_t *this,
-						   struct nlmsghdr *hdr)
-{
-	struct xfrm_user_expire *expire;
-	u_int32_t spi;
-	u_int8_t protocol;
-	host_t *dst;
-
-	expire = NLMSG_DATA(hdr);
-	protocol = expire->state.id.proto;
-	spi = expire->state.id.spi;
-
-	DBG2(DBG_KNL, "received a XFRM_MSG_EXPIRE");
-
-	if (protocol == IPPROTO_ESP || protocol == IPPROTO_AH)
-	{
-		dst = xfrm2host(expire->state.family, &expire->state.id.daddr, 0);
-		if (dst)
-		{
-			hydra->kernel_interface->expire(hydra->kernel_interface, protocol,
-											spi, dst, expire->hard != 0);
-			dst->destroy(dst);
-		}
-	}
-}
-
-/**
- * Process a XFRM_MSG_MIGRATE from kernel
- */
-static void process_migrate(private_kernel_netlink_ipsec_t *this,
-							struct nlmsghdr *hdr)
-{
-	struct xfrm_userpolicy_id *policy_id;
-	struct rtattr *rta;
-	size_t rtasize;
-	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;
-	u_int32_t reqid = 0;
-	policy_dir_t dir;
-
-	policy_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;
-
-			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);
-			reqid = migrate->reqid;
-			DBG2(DBG_KNL, "  migrate %H...%H to %H...%H, reqid {%u}",
-						   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)
-	{
-		hydra->kernel_interface->migrate(hydra->kernel_interface, reqid,
-										 src_ts, dst_ts, dir, local, remote);
-	}
-	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,
-							struct nlmsghdr *hdr)
-{
-	struct xfrm_user_mapping *mapping;
-	u_int32_t spi;
-
-	mapping = NLMSG_DATA(hdr);
-	spi = mapping->id.spi;
-
-	DBG2(DBG_KNL, "received a XFRM_MSG_MAPPING");
-
-	if (mapping->id.proto == IPPROTO_ESP)
-	{
-		host_t *dst, *new;
-
-		dst = xfrm2host(mapping->id.family, &mapping->id.daddr, 0);
-		if (dst)
-		{
-			new = xfrm2host(mapping->id.family, &mapping->new_saddr,
-							mapping->new_sport);
-			if (new)
-			{
-				hydra->kernel_interface->mapping(hydra->kernel_interface,
-												 IPPROTO_ESP, spi, dst, new);
-				new->destroy(new);
-			}
-			dst->destroy(dst);
-		}
-	}
-}
-
-/**
- * Receives events from kernel
- */
-static bool receive_events(private_kernel_netlink_ipsec_t *this, int fd,
-						   watcher_event_t event)
-{
-	char response[1024];
-	struct nlmsghdr *hdr = (struct nlmsghdr*)response;
-	struct sockaddr_nl addr;
-	socklen_t addr_len = sizeof(addr);
-	int len;
-
-	len = recvfrom(this->socket_xfrm_events, response, sizeof(response),
-				   MSG_DONTWAIT, (struct sockaddr*)&addr, &addr_len);
-	if (len < 0)
-	{
-		switch (errno)
-		{
-			case EINTR:
-				/* interrupted, try again */
-				return TRUE;
-			case EAGAIN:
-				/* no data ready, select again */
-				return TRUE;
-			default:
-				DBG1(DBG_KNL, "unable to receive from xfrm event socket");
-				sleep(1);
-				return TRUE;
-		}
-	}
-
-	if (addr.nl_pid != 0)
-	{	/* not from kernel. not interested, try another one */
-		return TRUE;
-	}
-
-	while (NLMSG_OK(hdr, len))
-	{
-		switch (hdr->nlmsg_type)
-		{
-			case XFRM_MSG_ACQUIRE:
-				process_acquire(this, hdr);
-				break;
-			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;
-			default:
-				DBG1(DBG_KNL, "received unknown event from xfrm event "
-							  "socket: %d", hdr->nlmsg_type);
-				break;
-		}
-		hdr = NLMSG_NEXT(hdr, len);
-	}
-	return TRUE;
-}
-
-METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
-	private_kernel_netlink_ipsec_t *this)
-{
-	return KERNEL_ESP_V3_TFC;
-}
-
-/**
- * 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 *spi)
-{
-	netlink_buf_t request;
-	struct nlmsghdr *hdr, *out;
-	struct xfrm_userspi_info *userspi;
-	u_int32_t received_spi = 0;
-	size_t len;
-
-	memset(&request, 0, sizeof(request));
-
-	hdr = &request.hdr;
-	hdr->nlmsg_flags = NLM_F_REQUEST;
-	hdr->nlmsg_type = XFRM_MSG_ALLOCSPI;
-	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userspi_info));
-
-	userspi = NLMSG_DATA(hdr);
-	host2xfrm(src, &userspi->info.saddr);
-	host2xfrm(dst, &userspi->info.id.daddr);
-	userspi->info.id.proto = proto;
-	userspi->info.mode = XFRM_MODE_TUNNEL;
-	userspi->info.family = src->get_family(src);
-	userspi->min = min;
-	userspi->max = max;
-
-	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:
-				{
-					struct xfrm_usersa_info* usersa = NLMSG_DATA(hdr);
-					received_spi = usersa->id.spi;
-					break;
-				}
-				case NLMSG_ERROR:
-				{
-					struct nlmsgerr *err = NLMSG_DATA(hdr);
-					DBG1(DBG_KNL, "allocating SPI failed: %s (%d)",
-						 strerror(-err->error), -err->error);
-					break;
-				}
-				default:
-					hdr = NLMSG_NEXT(hdr, len);
-					continue;
-				case NLMSG_DONE:
-					break;
-			}
-			break;
-		}
-		free(out);
-	}
-
-	if (received_spi == 0)
-	{
-		return FAILED;
-	}
-
-	*spi = received_spi;
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, get_spi, status_t,
-	private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
-	u_int8_t protocol, u_int32_t *spi)
-{
-	if (get_spi_internal(this, src, dst, protocol,
-						 0xc0000000, 0xcFFFFFFF, spi) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to get SPI");
-		return FAILED;
-	}
-
-	DBG2(DBG_KNL, "got SPI %.8x", ntohl(*spi));
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, get_cpi, status_t,
-	private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
-	u_int16_t *cpi)
-{
-	u_int32_t received_spi = 0;
-
-	if (get_spi_internal(this, src, dst, IPPROTO_COMP,
-						 0x100, 0xEFFF, &received_spi) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to get CPI");
-		return FAILED;
-	}
-
-	*cpi = htons((u_int16_t)ntohl(received_spi));
-
-	DBG2(DBG_KNL, "got CPI %.4x", ntohs(*cpi));
-	return SUCCESS;
-}
-
-/**
- * Add a XFRM mark to message if required
- */
-static bool add_mark(struct nlmsghdr *hdr, int buflen, mark_t mark)
-{
-	if (mark.value)
-	{
-		struct xfrm_mark *xmrk;
-
-		xmrk = netlink_reserve(hdr, buflen, XFRMA_MARK, sizeof(*xmrk));
-		if (!xmrk)
-		{
-			return FALSE;
-		}
-		xmrk->v = mark.value;
-		xmrk->m = mark.mask;
-	}
-	return TRUE;
-}
-
-METHOD(kernel_ipsec_t, add_sa, status_t,
-	private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
-	u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
-	u_int32_t tfc, lifetime_cfg_t *lifetime, 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, u_int32_t replay_window,
-	bool initiator, bool encap, bool esn, bool inbound, bool update,
-	linked_list_t* src_ts, linked_list_t* dst_ts)
-{
-	netlink_buf_t request;
-	char *alg_name;
-	struct nlmsghdr *hdr;
-	struct xfrm_usersa_info *sa;
-	u_int16_t icv_size = 64;
-	ipsec_mode_t original_mode = mode;
-	traffic_selector_t *first_src_ts, *first_dst_ts;
-	status_t status = FAILED;
-
-	/* 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)
-	{
-		lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}};
-		add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark,
-			   tfc, &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED,
-			   chunk_empty, mode, ipcomp, 0, 0, initiator, FALSE, FALSE,
-			   inbound, update, src_ts, dst_ts);
-		ipcomp = IPCOMP_NONE;
-		/* use transport mode ESP SA, IPComp uses tunnel mode */
-		mode = MODE_TRANSPORT;
-	}
-
-	memset(&request, 0, sizeof(request));
-
-	DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}  (mark "
-				  "%u/0x%08x)", ntohl(spi), reqid, mark.value, mark.mask);
-
-	hdr = &request.hdr;
-	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
-	hdr->nlmsg_type = update ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
-	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
-
-	sa = NLMSG_DATA(hdr);
-	host2xfrm(src, &sa->saddr);
-	host2xfrm(dst, &sa->id.daddr);
-	sa->id.spi = spi;
-	sa->id.proto = protocol;
-	sa->family = src->get_family(src);
-	sa->mode = mode2kernel(mode);
-	switch (mode)
-	{
-		case MODE_TUNNEL:
-			sa->flags |= XFRM_STATE_AF_UNSPEC;
-			break;
-		case MODE_BEET:
-		case MODE_TRANSPORT:
-			if (original_mode == MODE_TUNNEL)
-			{	/* don't install selectors for switched SAs.  because only one
-				 * selector can be installed other traffic would get dropped */
-				break;
-			}
-			if (src_ts->get_first(src_ts, (void**)&first_src_ts) == SUCCESS &&
-				dst_ts->get_first(dst_ts, (void**)&first_dst_ts) == SUCCESS)
-			{
-				sa->sel = ts2selector(first_src_ts, first_dst_ts);
-				if (!this->proto_port_transport)
-				{
-					/* don't install proto/port on SA. This would break
-					 * potential secondary SAs for the same address using a
-					 * different prot/port. */
-					sa->sel.proto = 0;
-					sa->sel.dport = sa->sel.dport_mask = 0;
-					sa->sel.sport = sa->sel.sport_mask = 0;
-				}
-			}
-			break;
-		default:
-			break;
-	}
-
-	sa->reqid = reqid;
-	sa->lft.soft_byte_limit = XFRM_LIMIT(lifetime->bytes.rekey);
-	sa->lft.hard_byte_limit = XFRM_LIMIT(lifetime->bytes.life);
-	sa->lft.soft_packet_limit = XFRM_LIMIT(lifetime->packets.rekey);
-	sa->lft.hard_packet_limit = XFRM_LIMIT(lifetime->packets.life);
-	/* we use lifetimes since added, not since used */
-	sa->lft.soft_add_expires_seconds = lifetime->time.rekey;
-	sa->lft.hard_add_expires_seconds = lifetime->time.life;
-	sa->lft.soft_use_expires_seconds = 0;
-	sa->lft.hard_use_expires_seconds = 0;
-
-	switch (enc_alg)
-	{
-		case ENCR_UNDEFINED:
-			/* no encryption */
-			break;
-		case ENCR_AES_CCM_ICV16:
-		case ENCR_AES_GCM_ICV16:
-		case ENCR_NULL_AUTH_AES_GMAC:
-		case ENCR_CAMELLIA_CCM_ICV16:
-		case ENCR_CHACHA20_POLY1305:
-			icv_size += 32;
-			/* FALL */
-		case ENCR_AES_CCM_ICV12:
-		case ENCR_AES_GCM_ICV12:
-		case ENCR_CAMELLIA_CCM_ICV12:
-			icv_size += 32;
-			/* FALL */
-		case ENCR_AES_CCM_ICV8:
-		case ENCR_AES_GCM_ICV8:
-		case ENCR_CAMELLIA_CCM_ICV8:
-		{
-			struct xfrm_algo_aead *algo;
-
-			alg_name = lookup_algorithm(ENCRYPTION_ALGORITHM, enc_alg);
-			if (alg_name == NULL)
-			{
-				DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
-						 encryption_algorithm_names, enc_alg);
-					goto failed;
-			}
-			DBG2(DBG_KNL, "  using encryption algorithm %N with key size %d",
-				 encryption_algorithm_names, enc_alg, enc_key.len * 8);
-
-			algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AEAD,
-								   sizeof(*algo) + enc_key.len);
-			if (!algo)
-			{
-				goto failed;
-			}
-			algo->alg_key_len = enc_key.len * 8;
-			algo->alg_icv_len = icv_size;
-			strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
-			algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
-			memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
-			break;
-		}
-		default:
-		{
-			struct xfrm_algo *algo;
-
-			alg_name = lookup_algorithm(ENCRYPTION_ALGORITHM, enc_alg);
-			if (alg_name == NULL)
-			{
-				DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
-					 encryption_algorithm_names, enc_alg);
-				goto failed;
-			}
-			DBG2(DBG_KNL, "  using encryption algorithm %N with key size %d",
-				 encryption_algorithm_names, enc_alg, enc_key.len * 8);
-
-			algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_CRYPT,
-								   sizeof(*algo) + enc_key.len);
-			if (!algo)
-			{
-				goto failed;
-			}
-			algo->alg_key_len = enc_key.len * 8;
-			strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
-			algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
-			memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
-		}
-	}
-
-	if (int_alg != AUTH_UNDEFINED)
-	{
-		u_int trunc_len = 0;
-
-		alg_name = lookup_algorithm(INTEGRITY_ALGORITHM, int_alg);
-		if (alg_name == NULL)
-		{
-			DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
-				 integrity_algorithm_names, int_alg);
-			goto failed;
-		}
-		DBG2(DBG_KNL, "  using integrity algorithm %N with key size %d",
-			 integrity_algorithm_names, int_alg, int_key.len * 8);
-
-		switch (int_alg)
-		{
-			case AUTH_HMAC_MD5_128:
-			case AUTH_HMAC_SHA2_256_128:
-				trunc_len = 128;
-				break;
-			case AUTH_HMAC_SHA1_160:
-				trunc_len = 160;
-				break;
-			default:
-				break;
-		}
-
-		if (trunc_len)
-		{
-			struct xfrm_algo_auth* algo;
-
-			/* the kernel uses SHA256 with 96 bit truncation by default,
-			 * use specified truncation size supported by newer kernels.
-			 * also use this for untruncated MD5 and SHA1. */
-			algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AUTH_TRUNC,
-								   sizeof(*algo) + int_key.len);
-			if (!algo)
-			{
-				goto failed;
-			}
-			algo->alg_key_len = int_key.len * 8;
-			algo->alg_trunc_len = trunc_len;
-			strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
-			algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
-			memcpy(algo->alg_key, int_key.ptr, int_key.len);
-		}
-		else
-		{
-			struct xfrm_algo* algo;
-
-			algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AUTH,
-								   sizeof(*algo) + int_key.len);
-			if (!algo)
-			{
-				goto failed;
-			}
-			algo->alg_key_len = int_key.len * 8;
-			strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
-			algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
-			memcpy(algo->alg_key, int_key.ptr, int_key.len);
-		}
-	}
-
-	if (ipcomp != IPCOMP_NONE)
-	{
-		struct xfrm_algo* algo;
-
-		alg_name = lookup_algorithm(COMPRESSION_ALGORITHM, ipcomp);
-		if (alg_name == NULL)
-		{
-			DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
-				 ipcomp_transform_names, ipcomp);
-			goto failed;
-		}
-		DBG2(DBG_KNL, "  using compression algorithm %N",
-			 ipcomp_transform_names, ipcomp);
-
-		algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_COMP,
-							   sizeof(*algo));
-		if (!algo)
-		{
-			goto failed;
-		}
-		algo->alg_key_len = 0;
-		strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
-		algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
-	}
-
-	if (encap)
-	{
-		struct xfrm_encap_tmpl *tmpl;
-
-		tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP, sizeof(*tmpl));
-		if (!tmpl)
-		{
-			goto failed;
-		}
-		tmpl->encap_type = UDP_ENCAP_ESPINUDP;
-		tmpl->encap_sport = htons(src->get_port(src));
-		tmpl->encap_dport = htons(dst->get_port(dst));
-		memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t));
-		/* encap_oa could probably be derived from the
-		 * traffic selectors [rfc4306, p39]. In the netlink kernel
-		 * implementation pluto does the same as we do here but it uses
-		 * encap_oa in the pfkey implementation.
-		 * BUT as /usr/src/linux/net/key/af_key.c indicates the kernel ignores
-		 * it anyway
-		 *   -> does that mean that NAT-T encap doesn't work in transport mode?
-		 * No. The reason the kernel ignores NAT-OA is that it recomputes
-		 * (or, rather, just ignores) the checksum. If packets pass the IPsec
-		 * checks it marks them "checksum ok" so OA isn't needed. */
-	}
-
-	if (!add_mark(hdr, sizeof(request), mark))
-	{
-		goto failed;
-	}
-
-	if (tfc && protocol == IPPROTO_ESP && mode == MODE_TUNNEL)
-	{	/* the kernel supports TFC padding only for tunnel mode ESP SAs */
-		u_int32_t *tfcpad;
-
-		tfcpad = netlink_reserve(hdr, sizeof(request), XFRMA_TFCPAD,
-								 sizeof(*tfcpad));
-		if (!tfcpad)
-		{
-			goto failed;
-		}
-		*tfcpad = tfc;
-	}
-
-	if (protocol != IPPROTO_COMP)
-	{
-		if (replay_window != 0 && (esn || replay_window > 32))
-		{
-			/* for ESN or larger replay windows we need the new
-			 * XFRMA_REPLAY_ESN_VAL attribute to configure a bitmap */
-			struct xfrm_replay_state_esn *replay;
-			u_int32_t bmp_size;
-
-			bmp_size = round_up(replay_window, sizeof(u_int32_t) * 8) / 8;
-			replay = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_ESN_VAL,
-									 sizeof(*replay) + bmp_size);
-			if (!replay)
-			{
-				goto failed;
-			}
-			/* bmp_len contains number uf __u32's */
-			replay->bmp_len = bmp_size / sizeof(u_int32_t);
-			replay->replay_window = replay_window;
-			DBG2(DBG_KNL, "  using replay window of %u packets", replay_window);
-
-			if (esn)
-			{
-				DBG2(DBG_KNL, "  using extended sequence numbers (ESN)");
-				sa->flags |= XFRM_STATE_ESN;
-			}
-		}
-		else
-		{
-			DBG2(DBG_KNL, "  using replay window of %u packets", replay_window);
-			sa->replay_window = replay_window;
-		}
-	}
-
-	if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
-	{
-		if (mark.value)
-		{
-			DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x  "
-						  "(mark %u/0x%08x)", ntohl(spi), mark.value, mark.mask);
-		}
-		else
-		{
-			DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
-		}
-		goto failed;
-	}
-
-	status = SUCCESS;
-
-failed:
-	memwipe(&request, sizeof(request));
-	return status;
-}
-
-/**
- * Get the ESN replay state (i.e. sequence numbers) of an SA.
- *
- * Allocates into one the replay state structure we get from the kernel.
- */
-static void get_replay_state(private_kernel_netlink_ipsec_t *this,
-							 u_int32_t spi, u_int8_t protocol,
-							 host_t *dst, mark_t mark,
-							 struct xfrm_replay_state_esn **replay_esn,
-							 u_int32_t *replay_esn_len,
-							 struct xfrm_replay_state **replay,
-							 struct xfrm_lifetime_cur **lifetime)
-{
-	netlink_buf_t request;
-	struct nlmsghdr *hdr, *out = NULL;
-	struct xfrm_aevent_id *out_aevent = NULL, *aevent_id;
-	size_t len;
-	struct rtattr *rta;
-	size_t rtasize;
-
-	memset(&request, 0, sizeof(request));
-
-	DBG2(DBG_KNL, "querying replay state from SAD entry with SPI %.8x",
-				   ntohl(spi));
-
-	hdr = &request.hdr;
-	hdr->nlmsg_flags = NLM_F_REQUEST;
-	hdr->nlmsg_type = XFRM_MSG_GETAE;
-	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id));
-
-	aevent_id = NLMSG_DATA(hdr);
-	aevent_id->flags = XFRM_AE_RVAL;
-
-	host2xfrm(dst, &aevent_id->sa_id.daddr);
-	aevent_id->sa_id.spi = spi;
-	aevent_id->sa_id.proto = protocol;
-	aevent_id->sa_id.family = dst->get_family(dst);
-
-	if (!add_mark(hdr, sizeof(request), mark))
-	{
-		return;
-	}
-
-	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_NEWAE:
-				{
-					out_aevent = NLMSG_DATA(hdr);
-					break;
-				}
-				case NLMSG_ERROR:
-				{
-					struct nlmsgerr *err = NLMSG_DATA(hdr);
-					DBG1(DBG_KNL, "querying replay state from SAD entry "
-								  "failed: %s (%d)", strerror(-err->error),
-								  -err->error);
-					break;
-				}
-				default:
-					hdr = NLMSG_NEXT(hdr, len);
-					continue;
-				case NLMSG_DONE:
-					break;
-			}
-			break;
-		}
-	}
-
-	if (out_aevent)
-	{
-		rta = XFRM_RTA(out, struct xfrm_aevent_id);
-		rtasize = XFRM_PAYLOAD(out, struct xfrm_aevent_id);
-		while (RTA_OK(rta, rtasize))
-		{
-			if (rta->rta_type == XFRMA_LTIME_VAL &&
-				RTA_PAYLOAD(rta) == sizeof(**lifetime))
-			{
-				free(*lifetime);
-				*lifetime = malloc(RTA_PAYLOAD(rta));
-				memcpy(*lifetime, RTA_DATA(rta), RTA_PAYLOAD(rta));
-			}
-			if (rta->rta_type == XFRMA_REPLAY_VAL &&
-				RTA_PAYLOAD(rta) == sizeof(**replay))
-			{
-				free(*replay);
-				*replay = malloc(RTA_PAYLOAD(rta));
-				memcpy(*replay, RTA_DATA(rta), RTA_PAYLOAD(rta));
-			}
-			if (rta->rta_type == XFRMA_REPLAY_ESN_VAL &&
-				RTA_PAYLOAD(rta) >= sizeof(**replay_esn))
-			{
-				free(*replay_esn);
-				*replay_esn = malloc(RTA_PAYLOAD(rta));
-				*replay_esn_len = RTA_PAYLOAD(rta);
-				memcpy(*replay_esn, RTA_DATA(rta), RTA_PAYLOAD(rta));
-			}
-			rta = RTA_NEXT(rta, rtasize);
-		}
-	}
-	free(out);
-}
-
-METHOD(kernel_ipsec_t, query_sa, status_t,
-	private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
-	u_int32_t spi, u_int8_t protocol, mark_t mark,
-	u_int64_t *bytes, u_int64_t *packets, time_t *time)
-{
-	netlink_buf_t request;
-	struct nlmsghdr *out = NULL, *hdr;
-	struct xfrm_usersa_id *sa_id;
-	struct xfrm_usersa_info *sa = NULL;
-	status_t status = FAILED;
-	size_t len;
-
-	memset(&request, 0, sizeof(request));
-
-	DBG2(DBG_KNL, "querying SAD entry with SPI %.8x  (mark %u/0x%08x)",
-				   ntohl(spi), mark.value, mark.mask);
-
-	hdr = &request.hdr;
-	hdr->nlmsg_flags = NLM_F_REQUEST;
-	hdr->nlmsg_type = XFRM_MSG_GETSA;
-	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
-
-	sa_id = NLMSG_DATA(hdr);
-	host2xfrm(dst, &sa_id->daddr);
-	sa_id->spi = spi;
-	sa_id->proto = protocol;
-	sa_id->family = dst->get_family(dst);
-
-	if (!add_mark(hdr, sizeof(request), mark))
-	{
-		return FAILED;
-	}
-
-	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);
-
-					if (mark.value)
-					{
-						DBG1(DBG_KNL, "querying SAD entry with SPI %.8x  "
-									  "(mark %u/0x%08x) failed: %s (%d)",
-									   ntohl(spi), mark.value, mark.mask,
-									   strerror(-err->error), -err->error);
-					}
-					else
-					{
-						DBG1(DBG_KNL, "querying SAD entry with SPI %.8x "
-									  "failed: %s (%d)", ntohl(spi),
-									   strerror(-err->error), -err->error);
-					}
-					break;
-				}
-				default:
-					hdr = NLMSG_NEXT(hdr, len);
-					continue;
-				case NLMSG_DONE:
-					break;
-			}
-			break;
-		}
-	}
-
-	if (sa == NULL)
-	{
-		DBG2(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi));
-	}
-	else
-	{
-		if (bytes)
-		{
-			*bytes = sa->curlft.bytes;
-		}
-		if (packets)
-		{
-			*packets = sa->curlft.packets;
-		}
-		if (time)
-		{	/* curlft contains an "use" time, but that contains a timestamp
-			 * of the first use, not the last. Last use time must be queried
-			 * on the policy on Linux */
-			*time = 0;
-		}
-		status = SUCCESS;
-	}
-	memwipe(out, len);
-	free(out);
-	return status;
-}
-
-METHOD(kernel_ipsec_t, del_sa, status_t,
-	private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
-	u_int32_t spi, u_int8_t protocol, u_int16_t cpi, mark_t mark)
-{
-	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, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0, mark);
-	}
-
-	memset(&request, 0, sizeof(request));
-
-	DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x  (mark %u/0x%08x)",
-				   ntohl(spi), mark.value, mark.mask);
-
-	hdr = &request.hdr;
-	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 = NLMSG_DATA(hdr);
-	host2xfrm(dst, &sa_id->daddr);
-	sa_id->spi = spi;
-	sa_id->proto = protocol;
-	sa_id->family = dst->get_family(dst);
-
-	if (!add_mark(hdr, sizeof(request), mark))
-	{
-		return FAILED;
-	}
-
-	switch (this->socket_xfrm->send_ack(this->socket_xfrm, hdr))
-	{
-		case SUCCESS:
-			DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x (mark %u/0x%08x)",
-				 ntohl(spi), mark.value, mark.mask);
-			return SUCCESS;
-		case NOT_FOUND:
-			return NOT_FOUND;
-		default:
-			if (mark.value)
-			{
-				DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x "
-					 "(mark %u/0x%08x)", ntohl(spi), mark.value, mark.mask);
-			}
-			else
-			{
-				DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x",
-					 ntohl(spi));
-			}
-			return FAILED;
-	}
-}
-
-METHOD(kernel_ipsec_t, update_sa, status_t,
-	private_kernel_netlink_ipsec_t *this, u_int32_t spi, u_int8_t protocol,
-	u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
-	bool old_encap, bool new_encap, mark_t mark)
-{
-	netlink_buf_t request;
-	struct nlmsghdr *hdr, *out = NULL;
-	struct xfrm_usersa_id *sa_id;
-	struct xfrm_usersa_info *out_sa = NULL, *sa;
-	size_t len;
-	struct rtattr *rta;
-	size_t rtasize;
-	struct xfrm_encap_tmpl* tmpl = NULL;
-	struct xfrm_replay_state *replay = NULL;
-	struct xfrm_replay_state_esn *replay_esn = NULL;
-	struct xfrm_lifetime_cur *lifetime = NULL;
-	u_int32_t replay_esn_len = 0;
-	status_t status = FAILED;
-
-	/* 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, mark);
-	}
-
-	memset(&request, 0, sizeof(request));
-
-	DBG2(DBG_KNL, "querying SAD entry with SPI %.8x for update", ntohl(spi));
-
-	/* query the existing SA first */
-	hdr = &request.hdr;
-	hdr->nlmsg_flags = NLM_F_REQUEST;
-	hdr->nlmsg_type = XFRM_MSG_GETSA;
-	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
-
-	sa_id = NLMSG_DATA(hdr);
-	host2xfrm(dst, &sa_id->daddr);
-	sa_id->spi = spi;
-	sa_id->proto = protocol;
-	sa_id->family = dst->get_family(dst);
-
-	if (!add_mark(hdr, sizeof(request), mark))
-	{
-		return FAILED;
-	}
-
-	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:
-				{
-					out_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 (out_sa == NULL)
-	{
-		DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi));
-		goto failed;
-	}
-
-	get_replay_state(this, spi, protocol, dst, mark, &replay_esn,
-					 &replay_esn_len, &replay, &lifetime);
-
-	/* delete the old SA (without affecting the IPComp SA) */
-	if (del_sa(this, src, dst, spi, protocol, 0, mark) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to delete old SAD entry with SPI %.8x",
-					   ntohl(spi));
-		goto failed;
-	}
-
-	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 = &request.hdr;
-	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
-	hdr->nlmsg_type = XFRM_MSG_NEWSA;
-	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
-	sa = NLMSG_DATA(hdr);
-	memcpy(sa, NLMSG_DATA(out), sizeof(struct xfrm_usersa_info));
-	sa->family = new_dst->get_family(new_dst);
-
-	if (!src->ip_equals(src, new_src))
-	{
-		host2xfrm(new_src, &sa->saddr);
-	}
-	if (!dst->ip_equals(dst, new_dst))
-	{
-		host2xfrm(new_dst, &sa->id.daddr);
-	}
-
-	rta = XFRM_RTA(out, struct xfrm_usersa_info);
-	rtasize = XFRM_PAYLOAD(out, struct xfrm_usersa_info);
-	while (RTA_OK(rta, rtasize))
-	{
-		/* copy all attributes, but not XFRMA_ENCAP if we are disabling it */
-		if (rta->rta_type != XFRMA_ENCAP || new_encap)
-		{
-			if (rta->rta_type == XFRMA_ENCAP)
-			{	/* update encap tmpl */
-				tmpl = RTA_DATA(rta);
-				tmpl->encap_sport = ntohs(new_src->get_port(new_src));
-				tmpl->encap_dport = ntohs(new_dst->get_port(new_dst));
-			}
-			netlink_add_attribute(hdr, rta->rta_type,
-								  chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)),
-								  sizeof(request));
-		}
-		rta = RTA_NEXT(rta, rtasize);
-	}
-
-	if (tmpl == NULL && new_encap)
-	{	/* add tmpl if we are enabling it */
-		tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP, sizeof(*tmpl));
-		if (!tmpl)
-		{
-			goto failed;
-		}
-		tmpl->encap_type = UDP_ENCAP_ESPINUDP;
-		tmpl->encap_sport = ntohs(new_src->get_port(new_src));
-		tmpl->encap_dport = ntohs(new_dst->get_port(new_dst));
-		memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t));
-	}
-
-	if (replay_esn)
-	{
-		struct xfrm_replay_state_esn *state;
-
-		state = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_ESN_VAL,
-								replay_esn_len);
-		if (!state)
-		{
-			goto failed;
-		}
-		memcpy(state, replay_esn, replay_esn_len);
-	}
-	else if (replay)
-	{
-		struct xfrm_replay_state *state;
-
-		state = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_VAL,
-								sizeof(*state));
-		if (!state)
-		{
-			goto failed;
-		}
-		memcpy(state, replay, sizeof(*state));
-	}
-	else
-	{
-		DBG1(DBG_KNL, "unable to copy replay state from old SAD entry with "
-			 "SPI %.8x", ntohl(spi));
-	}
-	if (lifetime)
-	{
-		struct xfrm_lifetime_cur *state;
-
-		state = netlink_reserve(hdr, sizeof(request), XFRMA_LTIME_VAL,
-								sizeof(*state));
-		if (!state)
-		{
-			goto failed;
-		}
-		memcpy(state, lifetime, sizeof(*state));
-	}
-	else
-	{
-		DBG1(DBG_KNL, "unable to copy usage stats from old SAD entry with "
-			 "SPI %.8x", ntohl(spi));
-	}
-
-	if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi));
-		goto failed;
-	}
-
-	status = SUCCESS;
-failed:
-	free(replay);
-	free(replay_esn);
-	free(lifetime);
-	memwipe(out, len);
-	memwipe(&request, sizeof(request));
-	free(out);
-
-	return status;
-}
-
-METHOD(kernel_ipsec_t, flush_sas, status_t,
-	private_kernel_netlink_ipsec_t *this)
-{
-	netlink_buf_t request;
-	struct nlmsghdr *hdr;
-	struct xfrm_usersa_flush *flush;
-	struct {
-		u_int8_t proto;
-		char *name;
-	} protos[] = {
-		{ IPPROTO_AH, "AH" },
-		{ IPPROTO_ESP, "ESP" },
-		{ IPPROTO_COMP, "IPComp" },
-	};
-	int i;
-
-	memset(&request, 0, sizeof(request));
-
-	hdr = &request.hdr;
-	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
-	hdr->nlmsg_type = XFRM_MSG_FLUSHSA;
-	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_flush));
-
-	flush = NLMSG_DATA(hdr);
-
-	for (i = 0; i < countof(protos); i++)
-	{
-		DBG2(DBG_KNL, "flushing all %s SAD entries", protos[i].name);
-
-		flush->proto = protos[i].proto;
-
-		if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
-		{
-			DBG1(DBG_KNL, "unable to flush %s SAD entries", protos[i].name);
-			return FAILED;
-		}
-	}
-	return SUCCESS;
-}
-
-/**
- * Add or update a policy in the kernel.
- *
- * Note: The mutex has to be locked when entering this function
- * and is unlocked here in any case.
- */
-static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
-	policy_entry_t *policy, policy_sa_t *mapping, bool update)
-{
-	netlink_buf_t request;
-	policy_entry_t clone;
-	ipsec_sa_t *ipsec = mapping->sa;
-	struct xfrm_userpolicy_info *policy_info;
-	struct nlmsghdr *hdr;
-	status_t status;
-	int i;
-
-	/* clone the policy so we are able to check it out again later */
-	memcpy(&clone, policy, sizeof(policy_entry_t));
-
-	memset(&request, 0, sizeof(request));
-	hdr = &request.hdr;
-	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
-	hdr->nlmsg_type = update ? XFRM_MSG_UPDPOLICY : XFRM_MSG_NEWPOLICY;
-	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info));
-
-	policy_info = NLMSG_DATA(hdr);
-	policy_info->sel = policy->sel;
-	policy_info->dir = policy->direction;
-
-	/* calculate priority based on selector size, small size = high prio */
-	policy_info->priority = mapping->priority;
-	policy_info->action = mapping->type != POLICY_DROP ? XFRM_POLICY_ALLOW
-													   : XFRM_POLICY_BLOCK;
-	policy_info->share = XFRM_SHARE_ANY;
-
-	/* policies don't expire */
-	policy_info->lft.soft_byte_limit = XFRM_INF;
-	policy_info->lft.soft_packet_limit = XFRM_INF;
-	policy_info->lft.hard_byte_limit = XFRM_INF;
-	policy_info->lft.hard_packet_limit = XFRM_INF;
-	policy_info->lft.soft_add_expires_seconds = 0;
-	policy_info->lft.hard_add_expires_seconds = 0;
-	policy_info->lft.soft_use_expires_seconds = 0;
-	policy_info->lft.hard_use_expires_seconds = 0;
-
-	if (mapping->type == POLICY_IPSEC)
-	{
-		struct xfrm_user_tmpl *tmpl;
-		struct {
-			u_int8_t proto;
-			bool use;
-		} protos[] = {
-			{ IPPROTO_COMP, ipsec->cfg.ipcomp.transform != IPCOMP_NONE },
-			{ IPPROTO_ESP, ipsec->cfg.esp.use },
-			{ IPPROTO_AH, ipsec->cfg.ah.use },
-		};
-		ipsec_mode_t proto_mode = ipsec->cfg.mode;
-		int count = 0;
-
-		for (i = 0; i < countof(protos); i++)
-		{
-			if (protos[i].use)
-			{
-				count++;
-			}
-		}
-		tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_TMPL,
-							   count * sizeof(*tmpl));
-		if (!tmpl)
-		{
-			this->mutex->unlock(this->mutex);
-			return FAILED;
-		}
-
-		for (i = 0; i < countof(protos); i++)
-		{
-			if (!protos[i].use)
-			{
-				continue;
-			}
-			tmpl->reqid = ipsec->cfg.reqid;
-			tmpl->id.proto = protos[i].proto;
-			tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
-			tmpl->mode = mode2kernel(proto_mode);
-			tmpl->optional = protos[i].proto == IPPROTO_COMP &&
-							 policy->direction != POLICY_OUT;
-			tmpl->family = ipsec->src->get_family(ipsec->src);
-
-			if (proto_mode == MODE_TUNNEL || proto_mode == MODE_BEET)
-			{	/* only for tunnel mode */
-				host2xfrm(ipsec->src, &tmpl->saddr);
-				host2xfrm(ipsec->dst, &tmpl->id.daddr);
-			}
-
-			tmpl++;
-
-			/* use transport mode for other SAs */
-			proto_mode = MODE_TRANSPORT;
-		}
-	}
-
-	if (!add_mark(hdr, sizeof(request), ipsec->mark))
-	{
-		this->mutex->unlock(this->mutex);
-		return FAILED;
-	}
-	this->mutex->unlock(this->mutex);
-
-	status = this->socket_xfrm->send_ack(this->socket_xfrm, hdr);
-	if (status == ALREADY_DONE && !update)
-	{
-		DBG1(DBG_KNL, "policy already exists, try to update it");
-		hdr->nlmsg_type = XFRM_MSG_UPDPOLICY;
-		status = this->socket_xfrm->send_ack(this->socket_xfrm, hdr);
-	}
-	if (status != SUCCESS)
-	{
-		return FAILED;
-	}
-
-	/* find the policy again */
-	this->mutex->lock(this->mutex);
-	policy = this->policies->get(this->policies, &clone);
-	if (!policy ||
-		 policy->used_by->find_first(policy->used_by,
-									 NULL, (void**)&mapping) != SUCCESS)
-	{	/* policy or mapping is already gone, ignore */
-		this->mutex->unlock(this->mutex);
-		return SUCCESS;
-	}
-
-	/* install a route, if:
-	 * - this is a forward policy (to just get one for each child)
-	 * - we are in tunnel/BEET mode or install a bypass policy
-	 * - routing is not disabled via strongswan.conf
-	 */
-	if (policy->direction == POLICY_FWD && this->install_routes &&
-		(mapping->type != POLICY_IPSEC || ipsec->cfg.mode != MODE_TRANSPORT))
-	{
-		policy_sa_fwd_t *fwd = (policy_sa_fwd_t*)mapping;
-		route_entry_t *route;
-		host_t *iface;
-
-		INIT(route,
-			.prefixlen = policy->sel.prefixlen_s,
-		);
-
-		if (hydra->kernel_interface->get_address_by_ts(hydra->kernel_interface,
-				fwd->dst_ts, &route->src_ip, NULL) == SUCCESS)
-		{
-			/* get the nexthop to src (src as we are in POLICY_FWD) */
-			if (!ipsec->src->is_anyaddr(ipsec->src))
-			{
-				route->gateway = hydra->kernel_interface->get_nexthop(
-											hydra->kernel_interface, ipsec->src,
-											-1, ipsec->dst);
-			}
-			else
-			{	/* for shunt policies */
-				iface = xfrm2host(policy->sel.family, &policy->sel.saddr, 0);
-				route->gateway = hydra->kernel_interface->get_nexthop(
-										hydra->kernel_interface, iface,
-										policy->sel.prefixlen_s, route->src_ip);
-				iface->destroy(iface);
-			}
-			route->dst_net = chunk_alloc(policy->sel.family == AF_INET ? 4 : 16);
-			memcpy(route->dst_net.ptr, &policy->sel.saddr, route->dst_net.len);
-
-			/* get the interface to install the route for. If we have a local
-			 * address, use it. Otherwise (for shunt policies) use the
-			 * routes source address. */
-			iface = ipsec->dst;
-			if (iface->is_anyaddr(iface))
-			{
-				iface = route->src_ip;
-			}
-			/* install route via outgoing interface */
-			if (!hydra->kernel_interface->get_interface(hydra->kernel_interface,
-														iface, &route->if_name))
-			{
-				this->mutex->unlock(this->mutex);
-				route_entry_destroy(route);
-				return SUCCESS;
-			}
-
-			if (policy->route)
-			{
-				route_entry_t *old = policy->route;
-				if (route_entry_equals(old, route))
-				{
-					this->mutex->unlock(this->mutex);
-					route_entry_destroy(route);
-					return SUCCESS;
-				}
-				/* uninstall previously installed route */
-				if (hydra->kernel_interface->del_route(hydra->kernel_interface,
-						old->dst_net, old->prefixlen, old->gateway,
-						old->src_ip, old->if_name) != SUCCESS)
-				{
-					DBG1(DBG_KNL, "error uninstalling route installed with "
-								  "policy %R === %R %N", fwd->src_ts,
-								   fwd->dst_ts, policy_dir_names,
-								   policy->direction);
-				}
-				route_entry_destroy(old);
-				policy->route = NULL;
-			}
-
-			DBG2(DBG_KNL, "installing route: %R via %H src %H dev %s",
-				 fwd->src_ts, route->gateway, route->src_ip, route->if_name);
-			switch (hydra->kernel_interface->add_route(
-								hydra->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;
-}
-
-METHOD(kernel_ipsec_t, add_policy, status_t,
-	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, policy_type_t type, ipsec_sa_cfg_t *sa,
-	mark_t mark, policy_priority_t priority)
-{
-	policy_entry_t *policy, *current;
-	policy_sa_t *assigned_sa, *current_sa;
-	enumerator_t *enumerator;
-	bool found = FALSE, update = TRUE;
-
-	/* create a policy */
-	INIT(policy,
-		.sel = ts2selector(src_ts, dst_ts),
-		.mark = mark.value & mark.mask,
-		.direction = direction,
-		.reqid = sa->reqid,
-	);
-
-	/* find the policy, which matches EXACTLY */
-	this->mutex->lock(this->mutex);
-	current = this->policies->get(this->policies, policy);
-	if (current)
-	{
-		if (current->reqid && sa->reqid && current->reqid != sa->reqid)
-		{
-			DBG1(DBG_CFG, "unable to install policy %R === %R %N (mark "
-				 "%u/0x%08x) for reqid %u, the same policy for reqid %u exists",
-				 src_ts, dst_ts, policy_dir_names, direction,
-				 mark.value, mark.mask, sa->reqid, current->reqid);
-			policy_entry_destroy(this, policy);
-			this->mutex->unlock(this->mutex);
-			return INVALID_STATE;
-		}
-		/* use existing policy */
-		DBG2(DBG_KNL, "policy %R === %R %N  (mark %u/0x%08x) "
-					  "already exists, increasing refcount",
-					   src_ts, dst_ts, policy_dir_names, direction,
-					   mark.value, mark.mask);
-		policy_entry_destroy(this, policy);
-		policy = current;
-		found = TRUE;
-	}
-	else
-	{	/* use the new one, if we have no such policy */
-		policy->used_by = linked_list_create();
-		this->policies->put(this->policies, policy, policy);
-	}
-
-	/* cache the assigned IPsec SA */
-	assigned_sa = policy_sa_create(this, direction, type, src, dst, src_ts,
-								   dst_ts, mark, sa);
-	assigned_sa->priority = get_priority(policy, priority);
-
-	/* insert the SA according to its priority */
-	enumerator = policy->used_by->create_enumerator(policy->used_by);
-	while (enumerator->enumerate(enumerator, (void**)&current_sa))
-	{
-		if (current_sa->priority >= assigned_sa->priority)
-		{
-			break;
-		}
-		update = FALSE;
-	}
-	policy->used_by->insert_before(policy->used_by, enumerator,
-								   assigned_sa);
-	enumerator->destroy(enumerator);
-
-	if (!update)
-	{	/* we don't update the policy if the priority is lower than that of
-		 * the currently installed one */
-		this->mutex->unlock(this->mutex);
-		return SUCCESS;
-	}
-
-	if (this->policy_update)
-	{
-		found = TRUE;
-	}
-
-	DBG2(DBG_KNL, "%s policy %R === %R %N  (mark %u/0x%08x)",
-				   found ? "updating" : "adding", src_ts, dst_ts,
-				   policy_dir_names, direction, mark.value, mark.mask);
-
-	if (add_policy_internal(this, policy, assigned_sa, found) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to %s policy %R === %R %N",
-					   found ? "update" : "add", src_ts, dst_ts,
-					   policy_dir_names, direction);
-		return FAILED;
-	}
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, query_policy, status_t,
-	private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts,
-	traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
-	time_t *use_time)
-{
-	netlink_buf_t request;
-	struct nlmsghdr *out = NULL, *hdr;
-	struct xfrm_userpolicy_id *policy_id;
-	struct xfrm_userpolicy_info *policy = NULL;
-	size_t len;
-
-	memset(&request, 0, sizeof(request));
-
-	DBG2(DBG_KNL, "querying policy %R === %R %N  (mark %u/0x%08x)",
-				   src_ts, dst_ts, policy_dir_names, direction,
-				   mark.value, mark.mask);
-
-	hdr = &request.hdr;
-	hdr->nlmsg_flags = NLM_F_REQUEST;
-	hdr->nlmsg_type = XFRM_MSG_GETPOLICY;
-	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id));
-
-	policy_id = NLMSG_DATA(hdr);
-	policy_id->sel = ts2selector(src_ts, dst_ts);
-	policy_id->dir = direction;
-
-	if (!add_mark(hdr, sizeof(request), mark))
-	{
-		return FAILED;
-	}
-
-	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_NEWPOLICY:
-				{
-					policy = NLMSG_DATA(hdr);
-					break;
-				}
-				case NLMSG_ERROR:
-				{
-					struct nlmsgerr *err = NLMSG_DATA(hdr);
-					DBG1(DBG_KNL, "querying policy failed: %s (%d)",
-								   strerror(-err->error), -err->error);
-					break;
-				}
-				default:
-					hdr = NLMSG_NEXT(hdr, len);
-					continue;
-				case NLMSG_DONE:
-					break;
-			}
-			break;
-		}
-	}
-
-	if (policy == NULL)
-	{
-		DBG2(DBG_KNL, "unable to query policy %R === %R %N", src_ts, dst_ts,
-					   policy_dir_names, direction);
-		free(out);
-		return FAILED;
-	}
-
-	if (policy->curlft.use_time)
-	{
-		/* we need the monotonic time, but the kernel returns system time. */
-		*use_time = time_monotonic(NULL) - (time(NULL) - policy->curlft.use_time);
-	}
-	else
-	{
-		*use_time = 0;
-	}
-
-	free(out);
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, del_policy, status_t,
-	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, policy_type_t type, ipsec_sa_cfg_t *sa,
-	mark_t mark, policy_priority_t prio)
-{
-	policy_entry_t *current, policy;
-	enumerator_t *enumerator;
-	policy_sa_t *mapping;
-	netlink_buf_t request;
-	struct nlmsghdr *hdr;
-	struct xfrm_userpolicy_id *policy_id;
-	bool is_installed = TRUE;
-	u_int32_t priority;
-	ipsec_sa_t assigned_sa = {
-		.src = src,
-		.dst = dst,
-		.mark = mark,
-		.cfg = *sa,
-	};
-
-	DBG2(DBG_KNL, "deleting policy %R === %R %N  (mark %u/0x%08x)",
-				   src_ts, dst_ts, policy_dir_names, direction,
-				   mark.value, mark.mask);
-
-	/* create a policy */
-	memset(&policy, 0, sizeof(policy_entry_t));
-	policy.sel = ts2selector(src_ts, dst_ts);
-	policy.mark = mark.value & mark.mask;
-	policy.direction = direction;
-
-	/* find the policy */
-	this->mutex->lock(this->mutex);
-	current = this->policies->get(this->policies, &policy);
-	if (!current)
-	{
-		if (mark.value)
-		{
-			DBG1(DBG_KNL, "deleting policy %R === %R %N  (mark %u/0x%08x) "
-						  "failed, not found", src_ts, dst_ts, policy_dir_names,
-						   direction, mark.value, mark.mask);
-		}
-		else
-		{
-			DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found",
-						   src_ts, dst_ts, policy_dir_names, direction);
-		}
-		this->mutex->unlock(this->mutex);
-		return NOT_FOUND;
-	}
-
-	/* remove mapping to SA by reqid and priority */
-	priority = get_priority(current, prio);
-	enumerator = current->used_by->create_enumerator(current->used_by);
-	while (enumerator->enumerate(enumerator, (void**)&mapping))
-	{
-		if (priority == mapping->priority && type == mapping->type &&
-			ipsec_sa_equals(mapping->sa, &assigned_sa))
-		{
-			current->used_by->remove_at(current->used_by, enumerator);
-			policy_sa_destroy(mapping, &direction, this);
-			break;
-		}
-		is_installed = FALSE;
-	}
-	enumerator->destroy(enumerator);
-
-	if (current->used_by->get_count(current->used_by) > 0)
-	{	/* policy is used by more SAs, keep in kernel */
-		DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
-		if (!is_installed)
-		{	/* no need to update as the policy was not installed for this SA */
-			this->mutex->unlock(this->mutex);
-			return SUCCESS;
-		}
-
-		DBG2(DBG_KNL, "updating policy %R === %R %N  (mark %u/0x%08x)",
-					   src_ts, dst_ts, policy_dir_names, direction,
-					   mark.value, mark.mask);
-
-		current->used_by->get_first(current->used_by, (void**)&mapping);
-		if (add_policy_internal(this, current, mapping, TRUE) != SUCCESS)
-		{
-			DBG1(DBG_KNL, "unable to update policy %R === %R %N",
-						   src_ts, dst_ts, policy_dir_names, direction);
-			return FAILED;
-		}
-		return SUCCESS;
-	}
-
-	memset(&request, 0, sizeof(request));
-
-	hdr = &request.hdr;
-	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
-	hdr->nlmsg_type = XFRM_MSG_DELPOLICY;
-	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id));
-
-	policy_id = NLMSG_DATA(hdr);
-	policy_id->sel = current->sel;
-	policy_id->dir = direction;
-
-	if (!add_mark(hdr, sizeof(request), mark))
-	{
-		this->mutex->unlock(this->mutex);
-		return FAILED;
-	}
-
-	if (current->route)
-	{
-		route_entry_t *route = current->route;
-		if (hydra->kernel_interface->del_route(hydra->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);
-		}
-	}
-
-	this->policies->remove(this->policies, current);
-	policy_entry_destroy(this, current);
-	this->mutex->unlock(this->mutex);
-
-	if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
-	{
-		if (mark.value)
-		{
-			DBG1(DBG_KNL, "unable to delete policy %R === %R %N  "
-						  "(mark %u/0x%08x)", src_ts, dst_ts, policy_dir_names,
-						   direction, mark.value, mark.mask);
-		}
-		else
-		{
-			DBG1(DBG_KNL, "unable to delete policy %R === %R %N",
-						   src_ts, dst_ts, policy_dir_names, direction);
-		}
-		return FAILED;
-	}
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, flush_policies, status_t,
-	private_kernel_netlink_ipsec_t *this)
-{
-	netlink_buf_t request;
-	struct nlmsghdr *hdr;
-
-	memset(&request, 0, sizeof(request));
-
-	DBG2(DBG_KNL, "flushing all policies from SPD");
-
-	hdr = &request.hdr;
-	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
-	hdr->nlmsg_type = XFRM_MSG_FLUSHPOLICY;
-	hdr->nlmsg_len = NLMSG_LENGTH(0); /* no data associated */
-
-	/* by adding an rtattr of type  XFRMA_POLICY_TYPE we could restrict this
-	 * to main or sub policies (default is main) */
-
-	if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to flush SPD entries");
-		return FAILED;
-	}
-	return SUCCESS;
-}
-
-/**
- * Bypass socket using a per-socket policy
- */
-static bool add_socket_bypass(private_kernel_netlink_ipsec_t *this,
-							  int fd, int family)
-{
-	struct xfrm_userpolicy_info policy;
-	u_int sol, ipsec_policy;
-
-	switch (family)
-	{
-		case AF_INET:
-			sol = SOL_IP;
-			ipsec_policy = IP_XFRM_POLICY;
-			break;
-		case AF_INET6:
-			sol = SOL_IPV6;
-			ipsec_policy = IPV6_XFRM_POLICY;
-			break;
-		default:
-			return FALSE;
-	}
-
-	memset(&policy, 0, sizeof(policy));
-	policy.action = XFRM_POLICY_ALLOW;
-	policy.sel.family = family;
-
-	policy.dir = XFRM_POLICY_OUT;
-	if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
-	{
-		DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
-					   strerror(errno));
-		return FALSE;
-	}
-	policy.dir = XFRM_POLICY_IN;
-	if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
-	{
-		DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
-					   strerror(errno));
-		return FALSE;
-	}
-	return TRUE;
-}
-
-/**
- * Port based IKE bypass policy
- */
-typedef struct {
-	/** address family */
-	int family;
-	/** layer 4 protocol */
-	int proto;
-	/** port number, network order */
-	u_int16_t port;
-} bypass_t;
-
-/**
- * Add or remove a bypass policy from/to kernel
- */
-static bool manage_bypass(private_kernel_netlink_ipsec_t *this,
-						  int type, policy_dir_t dir, bypass_t *bypass)
-{
-	netlink_buf_t request;
-	struct xfrm_selector *sel;
-	struct nlmsghdr *hdr;
-
-	memset(&request, 0, sizeof(request));
-	hdr = &request.hdr;
-	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
-	hdr->nlmsg_type = type;
-
-	if (type == XFRM_MSG_NEWPOLICY)
-	{
-		struct xfrm_userpolicy_info *policy;
-
-		hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info));
-
-		policy = NLMSG_DATA(hdr);
-		policy->dir = dir;
-		policy->priority = 32;
-		policy->action = XFRM_POLICY_ALLOW;
-		policy->share = XFRM_SHARE_ANY;
-
-		policy->lft.soft_byte_limit = XFRM_INF;
-		policy->lft.soft_packet_limit = XFRM_INF;
-		policy->lft.hard_byte_limit = XFRM_INF;
-		policy->lft.hard_packet_limit = XFRM_INF;
-
-		sel = &policy->sel;
-	}
-	else /* XFRM_MSG_DELPOLICY */
-	{
-		struct xfrm_userpolicy_id *policy;
-
-		hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id));
-
-		policy = NLMSG_DATA(hdr);
-		policy->dir = dir;
-
-		sel = &policy->sel;
-	}
-
-	sel->family = bypass->family;
-	sel->proto = bypass->proto;
-	if (dir == POLICY_IN)
-	{
-		sel->dport = bypass->port;
-		sel->dport_mask = 0xffff;
-	}
-	else
-	{
-		sel->sport = bypass->port;
-		sel->sport_mask = 0xffff;
-	}
-	return this->socket_xfrm->send_ack(this->socket_xfrm, hdr) == SUCCESS;
-}
-
-/**
- * Bypass socket using a port-based bypass policy
- */
-static bool add_port_bypass(private_kernel_netlink_ipsec_t *this,
-							int fd, int family)
-{
-	union {
-		struct sockaddr sa;
-		struct sockaddr_in in;
-		struct sockaddr_in6 in6;
-	} saddr;
-	socklen_t len;
-	bypass_t bypass = {
-		.family = family,
-	};
-
-	len = sizeof(saddr);
-	if (getsockname(fd, &saddr.sa, &len) != 0)
-	{
-		return FALSE;
-	}
-#ifdef SO_PROTOCOL /* since 2.6.32 */
-	len = sizeof(bypass.proto);
-	if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &bypass.proto, &len) != 0)
-#endif
-	{	/* assume UDP if SO_PROTOCOL not supported */
-		bypass.proto = IPPROTO_UDP;
-	}
-	switch (family)
-	{
-		case AF_INET:
-			bypass.port = saddr.in.sin_port;
-			break;
-		case AF_INET6:
-			bypass.port = saddr.in6.sin6_port;
-			break;
-		default:
-			return FALSE;
-	}
-
-	if (!manage_bypass(this, XFRM_MSG_NEWPOLICY, POLICY_IN, &bypass))
-	{
-		return FALSE;
-	}
-	if (!manage_bypass(this, XFRM_MSG_NEWPOLICY, POLICY_OUT, &bypass))
-	{
-		manage_bypass(this, XFRM_MSG_DELPOLICY, POLICY_IN, &bypass);
-		return FALSE;
-	}
-	array_insert(this->bypass, ARRAY_TAIL, &bypass);
-
-	return TRUE;
-}
-
-/**
- * Remove installed port based bypass policy
- */
-static void remove_port_bypass(bypass_t *bypass, int idx,
-							   private_kernel_netlink_ipsec_t *this)
-{
-	manage_bypass(this, XFRM_MSG_DELPOLICY, POLICY_OUT, bypass);
-	manage_bypass(this, XFRM_MSG_DELPOLICY, POLICY_IN, bypass);
-}
-
-METHOD(kernel_ipsec_t, bypass_socket, bool,
-	private_kernel_netlink_ipsec_t *this, int fd, int family)
-{
-	if (lib->settings->get_bool(lib->settings,
-					"%s.plugins.kernel-netlink.port_bypass", FALSE, lib->ns))
-	{
-		return add_port_bypass(this, fd, family);
-	}
-	return add_socket_bypass(this, fd, family);
-}
-
-METHOD(kernel_ipsec_t, enable_udp_decap, bool,
-	private_kernel_netlink_ipsec_t *this, int fd, int family, u_int16_t port)
-{
-	int type = UDP_ENCAP_ESPINUDP;
-
-	if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
-	{
-		DBG1(DBG_KNL, "unable to set UDP_ENCAP: %s", strerror(errno));
-		return FALSE;
-	}
-	return TRUE;
-}
-
-METHOD(kernel_ipsec_t, destroy, void,
-	private_kernel_netlink_ipsec_t *this)
-{
-	enumerator_t *enumerator;
-	policy_entry_t *policy;
-
-	array_destroy_function(this->bypass,
-						   (array_callback_t)remove_port_bypass, this);
-	if (this->socket_xfrm_events > 0)
-	{
-		lib->watcher->remove(lib->watcher, this->socket_xfrm_events);
-		close(this->socket_xfrm_events);
-	}
-	DESTROY_IF(this->socket_xfrm);
-	enumerator = this->policies->create_enumerator(this->policies);
-	while (enumerator->enumerate(enumerator, &policy, &policy))
-	{
-		policy_entry_destroy(this, policy);
-	}
-	enumerator->destroy(enumerator);
-	this->policies->destroy(this->policies);
-	this->sas->destroy(this->sas);
-	this->mutex->destroy(this->mutex);
-	free(this);
-}
-
-/*
- * Described in header.
- */
-kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
-{
-	private_kernel_netlink_ipsec_t *this;
-	bool register_for_events = TRUE;
-	FILE *f;
-
-	INIT(this,
-		.public = {
-			.interface = {
-				.get_features = _get_features,
-				.get_spi = _get_spi,
-				.get_cpi = _get_cpi,
-				.add_sa  = _add_sa,
-				.update_sa = _update_sa,
-				.query_sa = _query_sa,
-				.del_sa = _del_sa,
-				.flush_sas = _flush_sas,
-				.add_policy = _add_policy,
-				.query_policy = _query_policy,
-				.del_policy = _del_policy,
-				.flush_policies = _flush_policies,
-				.bypass_socket = _bypass_socket,
-				.enable_udp_decap = _enable_udp_decap,
-				.destroy = _destroy,
-			},
-		},
-		.policies = hashtable_create((hashtable_hash_t)policy_hash,
-									 (hashtable_equals_t)policy_equals, 32),
-		.sas = hashtable_create((hashtable_hash_t)ipsec_sa_hash,
-								(hashtable_equals_t)ipsec_sa_equals, 32),
-		.bypass = array_create(sizeof(bypass_t), 0),
-		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
-		.policy_update = lib->settings->get_bool(lib->settings,
-					"%s.plugins.kernel-netlink.policy_update", FALSE, lib->ns),
-		.install_routes = lib->settings->get_bool(lib->settings,
-							"%s.install_routes", TRUE, lib->ns),
-		.proto_port_transport = lib->settings->get_bool(lib->settings,
-						"%s.plugins.kernel-netlink.set_proto_port_transport_sa",
-						FALSE, lib->ns),
-	);
-
-	if (streq(lib->ns, "starter"))
-	{	/* starter has no threads, so we do not register for kernel events */
-		register_for_events = FALSE;
-	}
-
-	f = fopen("/proc/sys/net/core/xfrm_acq_expires", "w");
-	if (f)
-	{
-		fprintf(f, "%u", lib->settings->get_int(lib->settings,
-								"%s.plugins.kernel-netlink.xfrm_acq_expires",
-								DEFAULT_ACQUIRE_LIFETIME, lib->ns));
-		fclose(f);
-	}
-
-	this->socket_xfrm = netlink_socket_create(NETLINK_XFRM, xfrm_msg_names,
-				lib->settings->get_bool(lib->settings,
-					"%s.plugins.kernel-netlink.parallel_xfrm", FALSE, lib->ns));
-	if (!this->socket_xfrm)
-	{
-		destroy(this);
-		return NULL;
-	}
-
-	if (register_for_events)
-	{
-		struct sockaddr_nl addr;
-
-		memset(&addr, 0, sizeof(addr));
-		addr.nl_family = AF_NETLINK;
-
-		/* 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)
-		{
-			DBG1(DBG_KNL, "unable to create XFRM event socket");
-			destroy(this);
-			return NULL;
-		}
-		addr.nl_groups = XFRMNLGRP(ACQUIRE) | XFRMNLGRP(EXPIRE) |
-						 XFRMNLGRP(MIGRATE) | XFRMNLGRP(MAPPING);
-		if (bind(this->socket_xfrm_events, (struct sockaddr*)&addr, sizeof(addr)))
-		{
-			DBG1(DBG_KNL, "unable to bind XFRM event socket");
-			destroy(this);
-			return NULL;
-		}
-		lib->watcher->add(lib->watcher, this->socket_xfrm_events, WATCHER_READ,
-						  (watcher_cb_t)receive_events, this);
-	}
-
-	return &this->public;
-}
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
deleted file mode 100644
index 4e5e02d..0000000
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
+++ /dev/null
@@ -1,2685 +0,0 @@
-/*
- * Copyright (C) 2008-2014 Tobias Brunner
- * Copyright (C) 2005-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.
- */
-
-/*
- * Copyright (C) 2010 secunet Security Networks AG
- * Copyright (C) 2010 Thomas Egerer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include <sys/socket.h>
-#include <sys/utsname.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <unistd.h>
-#include <errno.h>
-#include <net/if.h>
-#ifdef HAVE_LINUX_FIB_RULES_H
-#include <linux/fib_rules.h>
-#endif
-
-#include "kernel_netlink_net.h"
-#include "kernel_netlink_shared.h"
-
-#include <hydra.h>
-#include <utils/debug.h>
-#include <threading/mutex.h>
-#include <threading/rwlock.h>
-#include <threading/rwlock_condvar.h>
-#include <threading/spinlock.h>
-#include <collections/hashtable.h>
-#include <collections/linked_list.h>
-#include <processing/jobs/callback_job.h>
-
-/** delay before firing roam events (ms) */
-#define ROAM_DELAY 100
-
-/** delay before reinstalling routes (ms) */
-#define ROUTE_DELAY 100
-
-/** maximum recursion when searching for addresses in get_route() */
-#define MAX_ROUTE_RECURSION 2
-
-#ifndef ROUTING_TABLE
-#define ROUTING_TABLE 0
-#endif
-
-#ifndef ROUTING_TABLE_PRIO
-#define ROUTING_TABLE_PRIO 0
-#endif
-
-ENUM(rt_msg_names, RTM_NEWLINK, RTM_GETRULE,
-	"RTM_NEWLINK",
-	"RTM_DELLINK",
-	"RTM_GETLINK",
-	"RTM_SETLINK",
-	"RTM_NEWADDR",
-	"RTM_DELADDR",
-	"RTM_GETADDR",
-	"31",
-	"RTM_NEWROUTE",
-	"RTM_DELROUTE",
-	"RTM_GETROUTE",
-	"35",
-	"RTM_NEWNEIGH",
-	"RTM_DELNEIGH",
-	"RTM_GETNEIGH",
-	"RTM_NEWRULE",
-	"RTM_DELRULE",
-	"RTM_GETRULE",
-);
-
-typedef struct addr_entry_t addr_entry_t;
-
-/**
- * IP address in an iface_entry_t
- */
-struct addr_entry_t {
-
-	/** the ip address */
-	host_t *ip;
-
-	/** address flags */
-	u_char flags;
-
-	/** scope of the address */
-	u_char scope;
-
-	/** number of times this IP is used, if virtual (i.e. managed by us) */
-	u_int refcount;
-
-	/** TRUE once it is installed, if virtual */
-	bool installed;
-};
-
-/**
- * destroy a addr_entry_t object
- */
-static void addr_entry_destroy(addr_entry_t *this)
-{
-	this->ip->destroy(this->ip);
-	free(this);
-}
-
-typedef struct iface_entry_t iface_entry_t;
-
-/**
- * A network interface on this system, containing addr_entry_t's
- */
-struct iface_entry_t {
-
-	/** interface index */
-	int ifindex;
-
-	/** name of the interface */
-	char ifname[IFNAMSIZ];
-
-	/** interface flags, as in netdevice(7) SIOCGIFFLAGS */
-	u_int flags;
-
-	/** list of addresses as host_t */
-	linked_list_t *addrs;
-
-	/** TRUE if usable by config */
-	bool usable;
-};
-
-/**
- * destroy an interface entry
- */
-static void iface_entry_destroy(iface_entry_t *this)
-{
-	this->addrs->destroy_function(this->addrs, (void*)addr_entry_destroy);
-	free(this);
-}
-
-/**
- * find an interface entry by index
- */
-static bool iface_entry_by_index(iface_entry_t *this, int *ifindex)
-{
-	return this->ifindex == *ifindex;
-}
-
-/**
- * find an interface entry by name
- */
-static bool iface_entry_by_name(iface_entry_t *this, char *ifname)
-{
-	return streq(this->ifname, ifname);
-}
-
-/**
- * check if an interface is up
- */
-static inline bool iface_entry_up(iface_entry_t *iface)
-{
-	return (iface->flags & IFF_UP) == IFF_UP;
-}
-
-/**
- * check if an interface is up and usable
- */
-static inline bool iface_entry_up_and_usable(iface_entry_t *iface)
-{
-	return iface->usable && iface_entry_up(iface);
-}
-
-typedef struct addr_map_entry_t addr_map_entry_t;
-
-/**
- * Entry that maps an IP address to an interface entry
- */
-struct addr_map_entry_t {
-	/** The IP address */
-	host_t *ip;
-
-	/** The address entry for this IP address */
-	addr_entry_t *addr;
-
-	/** The interface this address is installed on */
-	iface_entry_t *iface;
-};
-
-/**
- * Hash a addr_map_entry_t object, all entries with the same IP address
- * are stored in the same bucket
- */
-static u_int addr_map_entry_hash(addr_map_entry_t *this)
-{
-	return chunk_hash(this->ip->get_address(this->ip));
-}
-
-/**
- * Compare two addr_map_entry_t objects, two entries are equal if they are
- * installed on the same interface
- */
-static bool addr_map_entry_equals(addr_map_entry_t *a, addr_map_entry_t *b)
-{
-	return a->iface->ifindex == b->iface->ifindex &&
-		   a->ip->ip_equals(a->ip, b->ip);
-}
-
-/**
- * Used with get_match this finds an address entry if it is installed on
- * an up and usable interface
- */
-static bool addr_map_entry_match_up_and_usable(addr_map_entry_t *a,
-											   addr_map_entry_t *b)
-{
-	return iface_entry_up_and_usable(b->iface) &&
-		   a->ip->ip_equals(a->ip, b->ip);
-}
-
-/**
- * Used with get_match this finds an address entry if it is installed on
- * any active local interface
- */
-static bool addr_map_entry_match_up(addr_map_entry_t *a, addr_map_entry_t *b)
-{
-	return iface_entry_up(b->iface) && a->ip->ip_equals(a->ip, b->ip);
-}
-
-/**
- * Used with get_match this finds an address entry if it is installed on
- * any local interface
- */
-static bool addr_map_entry_match(addr_map_entry_t *a, addr_map_entry_t *b)
-{
-	return a->ip->ip_equals(a->ip, b->ip);
-}
-
-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;
-};
-
-/**
- * Clone a route_entry_t object.
- */
-static route_entry_t *route_entry_clone(route_entry_t *this)
-{
-	route_entry_t *route;
-
-	INIT(route,
-		.if_name = strdup(this->if_name),
-		.src_ip = this->src_ip->clone(this->src_ip),
-		.gateway = this->gateway ? this->gateway->clone(this->gateway) : NULL,
-		.dst_net = chunk_clone(this->dst_net),
-		.prefixlen = this->prefixlen,
-	);
-	return route;
-}
-
-/**
- * Destroy a route_entry_t object
- */
-static void route_entry_destroy(route_entry_t *this)
-{
-	free(this->if_name);
-	DESTROY_IF(this->src_ip);
-	DESTROY_IF(this->gateway);
-	chunk_free(&this->dst_net);
-	free(this);
-}
-
-/**
- * Hash a route_entry_t object
- */
-static u_int route_entry_hash(route_entry_t *this)
-{
-	return chunk_hash_inc(chunk_from_thing(this->prefixlen),
-						  chunk_hash(this->dst_net));
-}
-
-/**
- * Compare two route_entry_t objects
- */
-static bool route_entry_equals(route_entry_t *a, route_entry_t *b)
-{
-	if (a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
-		a->src_ip->ip_equals(a->src_ip, b->src_ip) &&
-		chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen)
-	{
-		return (!a->gateway && !b->gateway) || (a->gateway && b->gateway &&
-					a->gateway->ip_equals(a->gateway, b->gateway));
-	}
-	return FALSE;
-}
-
-typedef struct net_change_t net_change_t;
-
-/**
- * Queued network changes
- */
-struct net_change_t {
-	/** Name of the interface that got activated (or an IP appeared on) */
-	char *if_name;
-};
-
-/**
- * Destroy a net_change_t object
- */
-static void net_change_destroy(net_change_t *this)
-{
-	free(this->if_name);
-	free(this);
-}
-
-/**
- * Hash a net_change_t object
- */
-static u_int net_change_hash(net_change_t *this)
-{
-	return chunk_hash(chunk_create(this->if_name, strlen(this->if_name)));
-}
-
-/**
- * Compare two net_change_t objects
- */
-static bool net_change_equals(net_change_t *a, net_change_t *b)
-{
-	return streq(a->if_name, b->if_name);
-}
-
-typedef struct private_kernel_netlink_net_t private_kernel_netlink_net_t;
-
-/**
- * Private variables and functions of kernel_netlink_net class.
- */
-struct private_kernel_netlink_net_t {
-	/**
-	 * Public part of the kernel_netlink_net_t object.
-	 */
-	kernel_netlink_net_t public;
-
-	/**
-	 * lock to access various lists and maps
-	 */
-	rwlock_t *lock;
-
-	/**
-	 * condition variable to signal virtual IP add/removal
-	 */
-	rwlock_condvar_t *condvar;
-
-	/**
-	 * Cached list of interfaces and its addresses (iface_entry_t)
-	 */
-	linked_list_t *ifaces;
-
-	/**
-	 * Map for IP addresses to iface_entry_t objects (addr_map_entry_t)
-	 */
-	hashtable_t *addrs;
-
-	/**
-	 * Map for virtual IP addresses to iface_entry_t objects (addr_map_entry_t)
-	 */
-	hashtable_t *vips;
-
-	/**
-	 * netlink rt socket (routing)
-	 */
-	netlink_socket_t *socket;
-
-	/**
-	 * Netlink rt socket to receive address change events
-	 */
-	int socket_events;
-
-	/**
-	 * earliest time of the next roam event
-	 */
-	timeval_t next_roam;
-
-	/**
-	 * roam event due to address change
-	 */
-	bool roam_address;
-
-	/**
-	 * lock to check and update roam event time
-	 */
-	spinlock_t *roam_lock;
-
-	/**
-	 * routing table to install routes
-	 */
-	int routing_table;
-
-	/**
-	 * priority of used routing table
-	 */
-	int routing_table_prio;
-
-	/**
-	 * installed routes
-	 */
-	hashtable_t *routes;
-
-	/**
-	 * mutex for routes
-	 */
-	mutex_t *routes_lock;
-
-	/**
-	 * interface changes which may trigger route reinstallation
-	 */
-	hashtable_t *net_changes;
-
-	/**
-	 * mutex for route reinstallation triggers
-	 */
-	mutex_t *net_changes_lock;
-
-	/**
-	 * time of last route reinstallation
-	 */
-	timeval_t last_route_reinstall;
-
-	/**
-	 * whether to react to RTM_NEWROUTE or RTM_DELROUTE events
-	 */
-	bool process_route;
-
-	/**
-	 * whether to trigger roam events
-	 */
-	bool roam_events;
-
-	/**
-	 * whether to actually install virtual IPs
-	 */
-	bool install_virtual_ip;
-
-	/**
-	 * the name of the interface virtual IP addresses are installed on
-	 */
-	char *install_virtual_ip_on;
-
-	/**
-	 * whether preferred source addresses can be specified for IPv6 routes
-	 */
-	bool rta_prefsrc_for_ipv6;
-
-	/**
-	 * whether marks can be used in route lookups
-	 */
-	bool rta_mark;
-
-	/**
-	 * the mark excluded from the routing rule used for virtual IPs
-	 */
-	mark_t routing_mark;
-
-	/**
-	 * whether to prefer temporary IPv6 addresses over public ones
-	 */
-	bool prefer_temporary_addrs;
-
-	/**
-	 * list with routing tables to be excluded from route lookup
-	 */
-	linked_list_t *rt_exclude;
-
-	/**
-	 * MTU to set on installed routes
-	 */
-	u_int32_t mtu;
-
-	/**
-	 * MSS to set on installed routes
-	 */
-	u_int32_t mss;
-};
-
-/**
- * Forward declaration
- */
-static status_t manage_srcroute(private_kernel_netlink_net_t *this,
-								int nlmsg_type, int flags, chunk_t dst_net,
-								u_int8_t prefixlen, host_t *gateway,
-								host_t *src_ip, char *if_name);
-
-/**
- * Clear the queued network changes.
- */
-static void net_changes_clear(private_kernel_netlink_net_t *this)
-{
-	enumerator_t *enumerator;
-	net_change_t *change;
-
-	enumerator = this->net_changes->create_enumerator(this->net_changes);
-	while (enumerator->enumerate(enumerator, NULL, (void**)&change))
-	{
-		this->net_changes->remove_at(this->net_changes, enumerator);
-		net_change_destroy(change);
-	}
-	enumerator->destroy(enumerator);
-}
-
-/**
- * Act upon queued network changes.
- */
-static job_requeue_t reinstall_routes(private_kernel_netlink_net_t *this)
-{
-	enumerator_t *enumerator;
-	route_entry_t *route;
-
-	this->net_changes_lock->lock(this->net_changes_lock);
-	this->routes_lock->lock(this->routes_lock);
-
-	enumerator = this->routes->create_enumerator(this->routes);
-	while (enumerator->enumerate(enumerator, NULL, (void**)&route))
-	{
-		net_change_t *change, lookup = {
-			.if_name = route->if_name,
-		};
-		/* check if a change for the outgoing interface is queued */
-		change = this->net_changes->get(this->net_changes, &lookup);
-		if (!change)
-		{	/* in case src_ip is not on the outgoing interface */
-			if (this->public.interface.get_interface(&this->public.interface,
-												route->src_ip, &lookup.if_name))
-			{
-				if (!streq(lookup.if_name, route->if_name))
-				{
-					change = this->net_changes->get(this->net_changes, &lookup);
-				}
-				free(lookup.if_name);
-			}
-		}
-		if (change)
-		{
-			manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL,
-							route->dst_net, route->prefixlen, route->gateway,
-							route->src_ip, route->if_name);
-		}
-	}
-	enumerator->destroy(enumerator);
-	this->routes_lock->unlock(this->routes_lock);
-
-	net_changes_clear(this);
-	this->net_changes_lock->unlock(this->net_changes_lock);
-	return JOB_REQUEUE_NONE;
-}
-
-/**
- * Queue route reinstallation caused by network changes for a given interface.
- *
- * The route reinstallation is delayed for a while and only done once for
- * several calls during this delay, in order to avoid doing it too often.
- * The interface name is freed.
- */
-static void queue_route_reinstall(private_kernel_netlink_net_t *this,
-								  char *if_name)
-{
-	net_change_t *update, *found;
-	timeval_t now;
-	job_t *job;
-
-	INIT(update,
-		.if_name = if_name
-	);
-
-	this->net_changes_lock->lock(this->net_changes_lock);
-	found = this->net_changes->put(this->net_changes, update, update);
-	if (found)
-	{
-		net_change_destroy(found);
-	}
-	time_monotonic(&now);
-	if (timercmp(&now, &this->last_route_reinstall, >))
-	{
-		timeval_add_ms(&now, ROUTE_DELAY);
-		this->last_route_reinstall = now;
-
-		job = (job_t*)callback_job_create((callback_job_cb_t)reinstall_routes,
-										  this, NULL, NULL);
-		lib->scheduler->schedule_job_ms(lib->scheduler, job, ROUTE_DELAY);
-	}
-	this->net_changes_lock->unlock(this->net_changes_lock);
-}
-
-/**
- * check if the given IP is known as virtual IP and currently installed
- *
- * this function will also return TRUE if the virtual IP entry disappeared.
- * in that case the returned entry will be NULL.
- *
- * this->lock must be held when calling this function
- */
-static bool is_vip_installed_or_gone(private_kernel_netlink_net_t *this,
-									 host_t *ip, addr_map_entry_t **entry)
-{
-	addr_map_entry_t lookup = {
-		.ip = ip,
-	};
-
-	*entry = this->vips->get_match(this->vips, &lookup,
-								  (void*)addr_map_entry_match);
-	if (*entry == NULL)
-	{	/* the virtual IP disappeared */
-		return TRUE;
-	}
-	return (*entry)->addr->installed;
-}
-
-/**
- * check if the given IP is known as virtual IP
- *
- * this->lock must be held when calling this function
- */
-static bool is_known_vip(private_kernel_netlink_net_t *this, host_t *ip)
-{
-	addr_map_entry_t lookup = {
-		.ip = ip,
-	};
-
-	return this->vips->get_match(this->vips, &lookup,
-								(void*)addr_map_entry_match) != NULL;
-}
-
-/**
- * Add an address map entry
- */
-static void addr_map_entry_add(hashtable_t *map, addr_entry_t *addr,
-							   iface_entry_t *iface)
-{
-	addr_map_entry_t *entry;
-
-	INIT(entry,
-		.ip = addr->ip,
-		.addr = addr,
-		.iface = iface,
-	);
-	entry = map->put(map, entry, entry);
-	free(entry);
-}
-
-/**
- * Remove an address map entry
- */
-static void addr_map_entry_remove(hashtable_t *map, addr_entry_t *addr,
-								  iface_entry_t *iface)
-{
-	addr_map_entry_t *entry, lookup = {
-		.ip = addr->ip,
-		.addr = addr,
-		.iface = iface,
-	};
-
-	entry = map->remove(map, &lookup);
-	free(entry);
-}
-
-/**
- * Determine the type or scope of the given unicast IP address.  This is not
- * the same thing returned in rtm_scope/ifa_scope.
- *
- * We use return values as defined in RFC 6724 (referring to RFC 4291).
- */
-static u_char get_scope(host_t *ip)
-{
-	chunk_t addr;
-
-	addr = ip->get_address(ip);
-	switch (addr.len)
-	{
-		case 4:
-			/* we use the mapping defined in RFC 6724, 3.2 */
-			if (addr.ptr[0] == 127)
-			{	/* link-local, same as the IPv6 loopback address */
-				return 2;
-			}
-			if (addr.ptr[0] == 169 && addr.ptr[1] == 254)
-			{	/* link-local */
-				return 2;
-			}
-			break;
-		case 16:
-			if (IN6_IS_ADDR_LOOPBACK((struct in6_addr*)addr.ptr))
-			{	/* link-local, according to RFC 4291, 2.5.3 */
-				return 2;
-			}
-			if (IN6_IS_ADDR_LINKLOCAL((struct in6_addr*)addr.ptr))
-			{
-				return 2;
-			}
-			if (IN6_IS_ADDR_SITELOCAL((struct in6_addr*)addr.ptr))
-			{	/* deprecated, according to RFC 4291, 2.5.7 */
-				return 5;
-			}
-			break;
-		default:
-			break;
-	}
-	/* global */
-	return 14;
-}
-
-/**
- * Returns the length of the common prefix in bits up to the length of a's
- * prefix, defined by RFC 6724 as the portion of the address not including the
- * interface ID, which is 64-bit for most unicast addresses (see RFC 4291).
- */
-static u_char common_prefix(host_t *a, host_t *b)
-{
-	chunk_t aa, ba;
-	u_char byte, bits = 0, match;
-
-	aa = a->get_address(a);
-	ba = b->get_address(b);
-	for (byte = 0; byte < 8; byte++)
-	{
-		if (aa.ptr[byte] != ba.ptr[byte])
-		{
-			match = aa.ptr[byte] ^ ba.ptr[byte];
-			for (bits = 8; match; match >>= 1)
-			{
-				bits--;
-			}
-			break;
-		}
-	}
-	return byte * 8 + bits;
-}
-
-/**
- * Compare two IP addresses and return TRUE if the second address is the better
- * choice of the two to reach the destination.
- * For IPv6 we approximately follow RFC 6724.
- */
-static bool is_address_better(private_kernel_netlink_net_t *this,
-							  addr_entry_t *a, addr_entry_t *b, host_t *d)
-{
-	u_char sa, sb, sd, pa, pb;
-
-	/* rule 2: prefer appropriate scope */
-	if (d)
-	{
-		sa = get_scope(a->ip);
-		sb = get_scope(b->ip);
-		sd = get_scope(d);
-		if (sa < sb)
-		{
-			return sa < sd;
-		}
-		else if (sb < sa)
-		{
-			return sb >= sd;
-		}
-	}
-	if (a->ip->get_family(a->ip) == AF_INET)
-	{	/* stop here for IPv4, default to addresses found earlier */
-		return FALSE;
-	}
-	/* rule 3: avoid deprecated addresses (RFC 4862) */
-	if ((a->flags & IFA_F_DEPRECATED) != (b->flags & IFA_F_DEPRECATED))
-	{
-		return a->flags & IFA_F_DEPRECATED;
-	}
-	/* rule 4 is not applicable as we don't know if an address is a home or
-	 * care-of addresses.
-	 * rule 5 does not apply as we only compare addresses from one interface
-	 * rule 6 requires a policy table (optionally configurable) to match
-	 * configurable labels
-	 */
-	/* rule 7: prefer temporary addresses (WE REVERSE THIS BY DEFAULT!) */
-	if ((a->flags & IFA_F_TEMPORARY) != (b->flags & IFA_F_TEMPORARY))
-	{
-		if (this->prefer_temporary_addrs)
-		{
-			return b->flags & IFA_F_TEMPORARY;
-		}
-		return a->flags & IFA_F_TEMPORARY;
-	}
-	/* rule 8: use longest matching prefix */
-	if (d)
-	{
-		pa = common_prefix(a->ip, d);
-		pb = common_prefix(b->ip, d);
-		if (pa != pb)
-		{
-			return pb > pa;
-		}
-	}
-	/* default to addresses found earlier */
-	return FALSE;
-}
-
-/**
- * Get a non-virtual IP address on the given interface.
- *
- * If a candidate address is given, we first search for that address and if not
- * found return the address as above.
- * Returned host is a clone, has to be freed by caller.
- *
- * this->lock must be held when calling this function.
- */
-static host_t *get_interface_address(private_kernel_netlink_net_t *this,
-									 int ifindex, int family, host_t *dest,
-									 host_t *candidate)
-{
-	iface_entry_t *iface;
-	enumerator_t *addrs;
-	addr_entry_t *addr, *best = NULL;
-
-	if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index,
-								 (void**)&iface, &ifindex) == SUCCESS)
-	{
-		if (iface->usable)
-		{	/* only use interfaces not excluded by config */
-			addrs = iface->addrs->create_enumerator(iface->addrs);
-			while (addrs->enumerate(addrs, &addr))
-			{
-				if (addr->refcount ||
-					addr->ip->get_family(addr->ip) != family)
-				{	/* ignore virtual IP addresses and ensure family matches */
-					continue;
-				}
-				if (candidate && candidate->ip_equals(candidate, addr->ip))
-				{	/* stop if we find the candidate */
-					best = addr;
-					break;
-				}
-				else if (!best || is_address_better(this, best, addr, dest))
-				{
-					best = addr;
-				}
-			}
-			addrs->destroy(addrs);
-		}
-	}
-	return best ? best->ip->clone(best->ip) : NULL;
-}
-
-/**
- * callback function that raises the delayed roam event
- */
-static job_requeue_t roam_event(private_kernel_netlink_net_t *this)
-{
-	bool address;
-
-	this->roam_lock->lock(this->roam_lock);
-	address = this->roam_address;
-	this->roam_address = FALSE;
-	this->roam_lock->unlock(this->roam_lock);
-	hydra->kernel_interface->roam(hydra->kernel_interface, address);
-	return JOB_REQUEUE_NONE;
-}
-
-/**
- * fire a roaming event. we delay it for a bit and fire only one event
- * for multiple calls. otherwise we would create too many events.
- */
-static void fire_roam_event(private_kernel_netlink_net_t *this, bool address)
-{
-	timeval_t now;
-	job_t *job;
-
-	if (!this->roam_events)
-	{
-		return;
-	}
-
-	time_monotonic(&now);
-	this->roam_lock->lock(this->roam_lock);
-	this->roam_address |= address;
-	if (!timercmp(&now, &this->next_roam, >))
-	{
-		this->roam_lock->unlock(this->roam_lock);
-		return;
-	}
-	timeval_add_ms(&now, ROAM_DELAY);
-	this->next_roam = now;
-	this->roam_lock->unlock(this->roam_lock);
-
-	job = (job_t*)callback_job_create((callback_job_cb_t)roam_event,
-									  this, NULL, NULL);
-	lib->scheduler->schedule_job_ms(lib->scheduler, job, ROAM_DELAY);
-}
-
-/**
- * check if an interface with a given index is up and usable
- *
- * this->lock must be locked when calling this function
- */
-static bool is_interface_up_and_usable(private_kernel_netlink_net_t *this,
-									   int index)
-{
-	iface_entry_t *iface;
-
-	if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index,
-								 (void**)&iface, &index) == SUCCESS)
-	{
-		return iface_entry_up_and_usable(iface);
-	}
-	return FALSE;
-}
-
-/**
- * unregister the current addr_entry_t from the hashtable it is stored in
- *
- * this->lock must be locked when calling this function
- */
-static void addr_entry_unregister(addr_entry_t *addr, iface_entry_t *iface,
-								  private_kernel_netlink_net_t *this)
-{
-	if (addr->refcount)
-	{
-		addr_map_entry_remove(this->vips, addr, iface);
-		this->condvar->broadcast(this->condvar);
-		return;
-	}
-	addr_map_entry_remove(this->addrs, addr, iface);
-}
-
-/**
- * process RTM_NEWLINK/RTM_DELLINK from kernel
- */
-static void process_link(private_kernel_netlink_net_t *this,
-						 struct nlmsghdr *hdr, bool event)
-{
-	struct ifinfomsg* msg = NLMSG_DATA(hdr);
-	struct rtattr *rta = IFLA_RTA(msg);
-	size_t rtasize = IFLA_PAYLOAD (hdr);
-	enumerator_t *enumerator;
-	iface_entry_t *current, *entry = NULL;
-	char *name = NULL;
-	bool update = FALSE, update_routes = FALSE;
-
-	while (RTA_OK(rta, rtasize))
-	{
-		switch (rta->rta_type)
-		{
-			case IFLA_IFNAME:
-				name = RTA_DATA(rta);
-				break;
-		}
-		rta = RTA_NEXT(rta, rtasize);
-	}
-	if (!name)
-	{
-		name = "(unknown)";
-	}
-
-	this->lock->write_lock(this->lock);
-	switch (hdr->nlmsg_type)
-	{
-		case RTM_NEWLINK:
-		{
-			if (this->ifaces->find_first(this->ifaces,
-									(void*)iface_entry_by_index, (void**)&entry,
-									&msg->ifi_index) != SUCCESS)
-			{
-				INIT(entry,
-					.ifindex = msg->ifi_index,
-					.addrs = linked_list_create(),
-					.usable = hydra->kernel_interface->is_interface_usable(
-												hydra->kernel_interface, name),
-				);
-				this->ifaces->insert_last(this->ifaces, entry);
-			}
-			strncpy(entry->ifname, name, IFNAMSIZ);
-			entry->ifname[IFNAMSIZ-1] = '\0';
-			if (event && entry->usable)
-			{
-				if (!(entry->flags & IFF_UP) && (msg->ifi_flags & IFF_UP))
-				{
-					update = update_routes = TRUE;
-					DBG1(DBG_KNL, "interface %s activated", name);
-				}
-				if ((entry->flags & IFF_UP) && !(msg->ifi_flags & IFF_UP))
-				{
-					update = TRUE;
-					DBG1(DBG_KNL, "interface %s deactivated", name);
-				}
-			}
-			entry->flags = msg->ifi_flags;
-			break;
-		}
-		case RTM_DELLINK:
-		{
-			enumerator = this->ifaces->create_enumerator(this->ifaces);
-			while (enumerator->enumerate(enumerator, &current))
-			{
-				if (current->ifindex == msg->ifi_index)
-				{
-					if (event && current->usable)
-					{
-						update = TRUE;
-						DBG1(DBG_KNL, "interface %s deleted", current->ifname);
-					}
-					/* TODO: move virtual IPs installed on this interface to
-					 * another interface? */
-					this->ifaces->remove_at(this->ifaces, enumerator);
-					current->addrs->invoke_function(current->addrs,
-								(void*)addr_entry_unregister, current, this);
-					iface_entry_destroy(current);
-					break;
-				}
-			}
-			enumerator->destroy(enumerator);
-			break;
-		}
-	}
-	this->lock->unlock(this->lock);
-
-	if (update_routes && event)
-	{
-		queue_route_reinstall(this, strdup(name));
-	}
-
-	if (update && event)
-	{
-		fire_roam_event(this, TRUE);
-	}
-}
-
-/**
- * process RTM_NEWADDR/RTM_DELADDR from kernel
- */
-static void process_addr(private_kernel_netlink_net_t *this,
-						 struct nlmsghdr *hdr, bool event)
-{
-	struct ifaddrmsg* msg = NLMSG_DATA(hdr);
-	struct rtattr *rta = IFA_RTA(msg);
-	size_t rtasize = IFA_PAYLOAD (hdr);
-	host_t *host = NULL;
-	iface_entry_t *iface;
-	chunk_t local = chunk_empty, address = chunk_empty;
-	char *route_ifname = NULL;
-	bool update = FALSE, found = FALSE, changed = FALSE;
-
-	while (RTA_OK(rta, rtasize))
-	{
-		switch (rta->rta_type)
-		{
-			case IFA_LOCAL:
-				local.ptr = RTA_DATA(rta);
-				local.len = RTA_PAYLOAD(rta);
-				break;
-			case IFA_ADDRESS:
-				address.ptr = RTA_DATA(rta);
-				address.len = RTA_PAYLOAD(rta);
-				break;
-		}
-		rta = RTA_NEXT(rta, rtasize);
-	}
-
-	/* For PPP interfaces, we need the IFA_LOCAL address,
-	 * IFA_ADDRESS is the peers address. But IFA_LOCAL is
-	 * not included in all cases (IPv6?), so fallback to IFA_ADDRESS. */
-	if (local.ptr)
-	{
-		host = host_create_from_chunk(msg->ifa_family, local, 0);
-	}
-	else if (address.ptr)
-	{
-		host = host_create_from_chunk(msg->ifa_family, address, 0);
-	}
-
-	if (host == NULL)
-	{	/* bad family? */
-		return;
-	}
-
-	this->lock->write_lock(this->lock);
-	if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index,
-								 (void**)&iface, &msg->ifa_index) == SUCCESS)
-	{
-		addr_map_entry_t *entry, lookup = {
-			.ip = host,
-			.iface = iface,
-		};
-		addr_entry_t *addr;
-
-		entry = this->vips->get(this->vips, &lookup);
-		if (entry)
-		{
-			if (hdr->nlmsg_type == RTM_NEWADDR)
-			{	/* mark as installed and signal waiting threads */
-				entry->addr->installed = TRUE;
-			}
-			else
-			{	/* the address was already marked as uninstalled */
-				addr = entry->addr;
-				iface->addrs->remove(iface->addrs, addr, NULL);
-				addr_map_entry_remove(this->vips, addr, iface);
-				addr_entry_destroy(addr);
-			}
-			/* no roam events etc. for virtual IPs */
-			this->condvar->broadcast(this->condvar);
-			this->lock->unlock(this->lock);
-			host->destroy(host);
-			return;
-		}
-		entry = this->addrs->get(this->addrs, &lookup);
-		if (entry)
-		{
-			if (hdr->nlmsg_type == RTM_DELADDR)
-			{
-				found = TRUE;
-				addr = entry->addr;
-				iface->addrs->remove(iface->addrs, addr, NULL);
-				if (iface->usable)
-				{
-					changed = TRUE;
-					DBG1(DBG_KNL, "%H disappeared from %s", host,
-						 iface->ifname);
-				}
-				addr_map_entry_remove(this->addrs, addr, iface);
-				addr_entry_destroy(addr);
-			}
-		}
-		else
-		{
-			if (hdr->nlmsg_type == RTM_NEWADDR)
-			{
-				found = TRUE;
-				changed = TRUE;
-				route_ifname = strdup(iface->ifname);
-				INIT(addr,
-					.ip = host->clone(host),
-					.flags = msg->ifa_flags,
-					.scope = msg->ifa_scope,
-				);
-				iface->addrs->insert_last(iface->addrs, addr);
-				addr_map_entry_add(this->addrs, addr, iface);
-				if (event && iface->usable)
-				{
-					DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
-				}
-			}
-		}
-		if (found && (iface->flags & IFF_UP))
-		{
-			update = TRUE;
-		}
-		if (!iface->usable)
-		{	/* ignore events for interfaces excluded by config */
-			update = changed = FALSE;
-		}
-	}
-	this->lock->unlock(this->lock);
-
-	if (update && event && route_ifname)
-	{
-		queue_route_reinstall(this, route_ifname);
-	}
-	else
-	{
-		free(route_ifname);
-	}
-	host->destroy(host);
-
-	/* send an update to all IKE_SAs */
-	if (update && event && changed)
-	{
-		fire_roam_event(this, TRUE);
-	}
-}
-
-/**
- * process RTM_NEWROUTE and RTM_DELROUTE from kernel
- */
-static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *hdr)
-{
-	struct rtmsg* msg = NLMSG_DATA(hdr);
-	struct rtattr *rta = RTM_RTA(msg);
-	size_t rtasize = RTM_PAYLOAD(hdr);
-	u_int32_t rta_oif = 0;
-	host_t *host = NULL;
-
-	/* ignore routes added by us or in the local routing table (local addrs) */
-	if (msg->rtm_table && (msg->rtm_table == this->routing_table ||
-						   msg->rtm_table == RT_TABLE_LOCAL))
-	{
-		return;
-	}
-	else if (msg->rtm_flags & RTM_F_CLONED)
-	{	/* ignore cached routes, seem to be created a lot for IPv6 */
-		return;
-	}
-
-	while (RTA_OK(rta, rtasize))
-	{
-		switch (rta->rta_type)
-		{
-			case RTA_PREFSRC:
-				DESTROY_IF(host);
-				host = host_create_from_chunk(msg->rtm_family,
-							chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)), 0);
-				break;
-			case RTA_OIF:
-				if (RTA_PAYLOAD(rta) == sizeof(rta_oif))
-				{
-					rta_oif = *(u_int32_t*)RTA_DATA(rta);
-				}
-				break;
-		}
-		rta = RTA_NEXT(rta, rtasize);
-	}
-	this->lock->read_lock(this->lock);
-	if (rta_oif && !is_interface_up_and_usable(this, rta_oif))
-	{	/* ignore route changes for interfaces that are ignored or down */
-		this->lock->unlock(this->lock);
-		DESTROY_IF(host);
-		return;
-	}
-	if (!host && rta_oif)
-	{
-		host = get_interface_address(this, rta_oif, msg->rtm_family,
-									 NULL, NULL);
-	}
-	if (!host || is_known_vip(this, host))
-	{	/* ignore routes added for virtual IPs */
-		this->lock->unlock(this->lock);
-		DESTROY_IF(host);
-		return;
-	}
-	this->lock->unlock(this->lock);
-	fire_roam_event(this, FALSE);
-	host->destroy(host);
-}
-
-/**
- * Receives events from kernel
- */
-static bool receive_events(private_kernel_netlink_net_t *this, int fd,
-						   watcher_event_t event)
-{
-	char response[1536];
-	struct nlmsghdr *hdr = (struct nlmsghdr*)response;
-	struct sockaddr_nl addr;
-	socklen_t addr_len = sizeof(addr);
-	int len;
-
-	len = recvfrom(this->socket_events, response, sizeof(response),
-				   MSG_DONTWAIT, (struct sockaddr*)&addr, &addr_len);
-	if (len < 0)
-	{
-		switch (errno)
-		{
-			case EINTR:
-				/* interrupted, try again */
-				return TRUE;
-			case EAGAIN:
-				/* no data ready, select again */
-				return TRUE;
-			default:
-				DBG1(DBG_KNL, "unable to receive from rt event socket");
-				sleep(1);
-				return TRUE;
-		}
-	}
-
-	if (addr.nl_pid != 0)
-	{	/* not from kernel. not interested, try another one */
-		return TRUE;
-	}
-
-	while (NLMSG_OK(hdr, len))
-	{
-		/* looks good so far, dispatch netlink message */
-		switch (hdr->nlmsg_type)
-		{
-			case RTM_NEWADDR:
-			case RTM_DELADDR:
-				process_addr(this, hdr, TRUE);
-				break;
-			case RTM_NEWLINK:
-			case RTM_DELLINK:
-				process_link(this, hdr, TRUE);
-				break;
-			case RTM_NEWROUTE:
-			case RTM_DELROUTE:
-				if (this->process_route)
-				{
-					process_route(this, hdr);
-				}
-				break;
-			default:
-				break;
-		}
-		hdr = NLMSG_NEXT(hdr, len);
-	}
-	return TRUE;
-}
-
-/** enumerator over addresses */
-typedef struct {
-	private_kernel_netlink_net_t* this;
-	/** which addresses to enumerate */
-	kernel_address_type_t which;
-} address_enumerator_t;
-
-/**
- * cleanup function for address enumerator
- */
-static void address_enumerator_destroy(address_enumerator_t *data)
-{
-	data->this->lock->unlock(data->this->lock);
-	free(data);
-}
-
-/**
- * filter for addresses
- */
-static bool filter_addresses(address_enumerator_t *data,
-							 addr_entry_t** in, host_t** out)
-{
-	if (!(data->which & ADDR_TYPE_VIRTUAL) && (*in)->refcount)
-	{	/* skip virtual interfaces added by us */
-		return FALSE;
-	}
-	if (!(data->which & ADDR_TYPE_REGULAR) && !(*in)->refcount)
-	{	/* address is regular, but not requested */
-		return FALSE;
-	}
-	if ((*in)->scope >= RT_SCOPE_LINK)
-	{	/* skip addresses with a unusable scope */
-		return FALSE;
-	}
-	*out = (*in)->ip;
-	return TRUE;
-}
-
-/**
- * enumerator constructor for interfaces
- */
-static enumerator_t *create_iface_enumerator(iface_entry_t *iface,
-											 address_enumerator_t *data)
-{
-	return enumerator_create_filter(
-				iface->addrs->create_enumerator(iface->addrs),
-				(void*)filter_addresses, data, NULL);
-}
-
-/**
- * filter for interfaces
- */
-static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in,
-							  iface_entry_t** out)
-{
-	if (!(data->which & ADDR_TYPE_IGNORED) && !(*in)->usable)
-	{	/* skip interfaces excluded by config */
-		return FALSE;
-	}
-	if (!(data->which & ADDR_TYPE_LOOPBACK) && ((*in)->flags & IFF_LOOPBACK))
-	{	/* ignore loopback devices */
-		return FALSE;
-	}
-	if (!(data->which & ADDR_TYPE_DOWN) && !((*in)->flags & IFF_UP))
-	{	/* skip interfaces not up */
-		return FALSE;
-	}
-	*out = *in;
-	return TRUE;
-}
-
-METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
-	private_kernel_netlink_net_t *this, kernel_address_type_t which)
-{
-	address_enumerator_t *data;
-
-	INIT(data,
-		.this = this,
-		.which = which,
-	);
-
-	this->lock->read_lock(this->lock);
-	return enumerator_create_nested(
-				enumerator_create_filter(
-					this->ifaces->create_enumerator(this->ifaces),
-					(void*)filter_interfaces, data, NULL),
-				(void*)create_iface_enumerator, data,
-				(void*)address_enumerator_destroy);
-}
-
-METHOD(kernel_net_t, get_interface_name, bool,
-	private_kernel_netlink_net_t *this, host_t* ip, char **name)
-{
-	addr_map_entry_t *entry, lookup = {
-		.ip = ip,
-	};
-
-	if (ip->is_anyaddr(ip))
-	{
-		return FALSE;
-	}
-	this->lock->read_lock(this->lock);
-	/* first try to find it on an up and usable interface */
-	entry = this->addrs->get_match(this->addrs, &lookup,
-								  (void*)addr_map_entry_match_up_and_usable);
-	if (entry)
-	{
-		if (name)
-		{
-			*name = strdup(entry->iface->ifname);
-			DBG2(DBG_KNL, "%H is on interface %s", ip, *name);
-		}
-		this->lock->unlock(this->lock);
-		return TRUE;
-	}
-	/* in a second step, consider virtual IPs installed by us */
-	entry = this->vips->get_match(this->vips, &lookup,
-								  (void*)addr_map_entry_match_up_and_usable);
-	if (entry)
-	{
-		if (name)
-		{
-			*name = strdup(entry->iface->ifname);
-			DBG2(DBG_KNL, "virtual IP %H is on interface %s", ip, *name);
-		}
-		this->lock->unlock(this->lock);
-		return TRUE;
-	}
-	/* maybe it is installed on an ignored interface */
-	entry = this->addrs->get_match(this->addrs, &lookup,
-								  (void*)addr_map_entry_match_up);
-	if (!entry)
-	{
-		DBG2(DBG_KNL, "%H is not a local address or the interface is down", ip);
-	}
-	this->lock->unlock(this->lock);
-	return FALSE;
-}
-
-/**
- * get the index of an interface by name
- */
-static int get_interface_index(private_kernel_netlink_net_t *this, char* name)
-{
-	iface_entry_t *iface;
-	int ifindex = 0;
-
-	DBG2(DBG_KNL, "getting iface index for %s", name);
-
-	this->lock->read_lock(this->lock);
-	if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_name,
-								(void**)&iface, name) == SUCCESS)
-	{
-		ifindex = iface->ifindex;
-	}
-	this->lock->unlock(this->lock);
-
-	if (ifindex == 0)
-	{
-		DBG1(DBG_KNL, "unable to get interface index for %s", name);
-	}
-	return ifindex;
-}
-
-/**
- * check if an address or net (addr with prefix net bits) is in
- * subnet (net with net_len net bits)
- */
-static bool addr_in_subnet(chunk_t addr, int prefix, chunk_t net, int net_len)
-{
-	static const u_char mask[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
-	int byte = 0;
-
-	if (net_len == 0)
-	{	/* any address matches a /0 network */
-		return TRUE;
-	}
-	if (addr.len != net.len || net_len > 8 * net.len || prefix < net_len)
-	{
-		return FALSE;
-	}
-	/* scan through all bytes in network order */
-	while (net_len > 0)
-	{
-		if (net_len < 8)
-		{
-			return (mask[net_len] & addr.ptr[byte]) == (mask[net_len] & net.ptr[byte]);
-		}
-		else
-		{
-			if (addr.ptr[byte] != net.ptr[byte])
-			{
-				return FALSE;
-			}
-			byte++;
-			net_len -= 8;
-		}
-	}
-	return TRUE;
-}
-
-/**
- * Store information about a route retrieved via RTNETLINK
- */
-typedef struct {
-	chunk_t gtw;
-	chunk_t src;
-	chunk_t dst;
-	host_t *src_host;
-	u_int8_t dst_len;
-	u_int32_t table;
-	u_int32_t oif;
-	u_int32_t priority;
-} rt_entry_t;
-
-/**
- * Free a route entry
- */
-static void rt_entry_destroy(rt_entry_t *this)
-{
-	DESTROY_IF(this->src_host);
-	free(this);
-}
-
-/**
- * Check if the route received with RTM_NEWROUTE is usable based on its type.
- */
-static bool route_usable(struct nlmsghdr *hdr)
-{
-	struct rtmsg *msg;
-
-	msg = NLMSG_DATA(hdr);
-	switch (msg->rtm_type)
-	{
-		case RTN_BLACKHOLE:
-		case RTN_UNREACHABLE:
-		case RTN_PROHIBIT:
-		case RTN_THROW:
-			return FALSE;
-		default:
-			return TRUE;
-	}
-}
-
-/**
- * Parse route received with RTM_NEWROUTE. The given rt_entry_t object will be
- * reused if not NULL.
- *
- * Returned chunks point to internal data of the Netlink message.
- */
-static rt_entry_t *parse_route(struct nlmsghdr *hdr, rt_entry_t *route)
-{
-	struct rtattr *rta;
-	struct rtmsg *msg;
-	size_t rtasize;
-
-	msg = NLMSG_DATA(hdr);
-	rta = RTM_RTA(msg);
-	rtasize = RTM_PAYLOAD(hdr);
-
-	if (route)
-	{
-		route->gtw = chunk_empty;
-		route->src = chunk_empty;
-		route->dst = chunk_empty;
-		route->dst_len = msg->rtm_dst_len;
-		route->table = msg->rtm_table;
-		route->oif = 0;
-		route->priority = 0;
-	}
-	else
-	{
-		INIT(route,
-			.dst_len = msg->rtm_dst_len,
-			.table = msg->rtm_table,
-		);
-	}
-
-	while (RTA_OK(rta, rtasize))
-	{
-		switch (rta->rta_type)
-		{
-			case RTA_PREFSRC:
-				route->src = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
-				break;
-			case RTA_GATEWAY:
-				route->gtw = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
-				break;
-			case RTA_DST:
-				route->dst = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
-				break;
-			case RTA_OIF:
-				if (RTA_PAYLOAD(rta) == sizeof(route->oif))
-				{
-					route->oif = *(u_int32_t*)RTA_DATA(rta);
-				}
-				break;
-			case RTA_PRIORITY:
-				if (RTA_PAYLOAD(rta) == sizeof(route->priority))
-				{
-					route->priority = *(u_int32_t*)RTA_DATA(rta);
-				}
-				break;
-#ifdef HAVE_RTA_TABLE
-			case RTA_TABLE:
-				if (RTA_PAYLOAD(rta) == sizeof(route->table))
-				{
-					route->table = *(u_int32_t*)RTA_DATA(rta);
-				}
-				break;
-#endif /* HAVE_RTA_TABLE*/
-		}
-		rta = RTA_NEXT(rta, rtasize);
-	}
-	return route;
-}
-
-/**
- * Get a route: If "nexthop", the nexthop is returned. source addr otherwise.
- */
-static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
-						 int prefix, bool nexthop, host_t *candidate,
-						 u_int recursion)
-{
-	netlink_buf_t request;
-	struct nlmsghdr *hdr, *out, *current;
-	struct rtmsg *msg;
-	chunk_t chunk;
-	size_t len;
-	linked_list_t *routes;
-	rt_entry_t *route = NULL, *best = NULL;
-	enumerator_t *enumerator;
-	host_t *addr = NULL;
-	bool match_net;
-	int family;
-
-	if (recursion > MAX_ROUTE_RECURSION)
-	{
-		return NULL;
-	}
-	chunk = dest->get_address(dest);
-	len = chunk.len * 8;
-	prefix = prefix < 0 ? len : min(prefix, len);
-	match_net = prefix != len;
-
-	memset(&request, 0, sizeof(request));
-
-	family = dest->get_family(dest);
-	hdr = &request.hdr;
-	hdr->nlmsg_flags = NLM_F_REQUEST;
-	hdr->nlmsg_type = RTM_GETROUTE;
-	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
-
-	msg = NLMSG_DATA(hdr);
-	msg->rtm_family = family;
-	if (!match_net && this->rta_mark && this->routing_mark.value)
-	{
-		/* if our routing rule excludes packets with a certain mark we can
-		 * get the preferred route without having to dump all routes */
-		chunk = chunk_from_thing(this->routing_mark.value);
-		netlink_add_attribute(hdr, RTA_MARK, chunk, sizeof(request));
-	}
-	else if (family == AF_INET || this->rta_prefsrc_for_ipv6 ||
-			 this->routing_table || match_net)
-	{	/* kernels prior to 3.0 do not support RTA_PREFSRC for IPv6 routes.
-		 * as we want to ignore routes with virtual IPs we cannot use DUMP
-		 * if these routes are not installed in a separate table */
-		hdr->nlmsg_flags |= NLM_F_DUMP;
-	}
-	if (candidate)
-	{
-		chunk = candidate->get_address(candidate);
-		netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request));
-	}
-	if (!match_net)
-	{
-		chunk = dest->get_address(dest);
-		netlink_add_attribute(hdr, RTA_DST, chunk, sizeof(request));
-	}
-
-	if (this->socket->send(this->socket, hdr, &out, &len) != SUCCESS)
-	{
-		DBG2(DBG_KNL, "getting %s to reach %H/%d failed",
-			 nexthop ? "nexthop" : "address", dest, prefix);
-		return NULL;
-	}
-	routes = linked_list_create();
-	this->lock->read_lock(this->lock);
-
-	for (current = out; NLMSG_OK(current, len);
-		 current = NLMSG_NEXT(current, len))
-	{
-		switch (current->nlmsg_type)
-		{
-			case NLMSG_DONE:
-				break;
-			case RTM_NEWROUTE:
-			{
-				rt_entry_t *other;
-				uintptr_t table;
-
-				if (!route_usable(current))
-				{
-					continue;
-				}
-				route = parse_route(current, route);
-
-				table = (uintptr_t)route->table;
-				if (this->rt_exclude->find_first(this->rt_exclude, NULL,
-												 (void**)&table) == SUCCESS)
-				{	/* route is from an excluded routing table */
-					continue;
-				}
-				if (this->routing_table != 0 &&
-					route->table == this->routing_table)
-				{	/* route is from our own ipsec routing table */
-					continue;
-				}
-				if (route->oif && !is_interface_up_and_usable(this, route->oif))
-				{	/* interface is down */
-					continue;
-				}
-				if (!addr_in_subnet(chunk, prefix, route->dst, route->dst_len))
-				{	/* route destination does not contain dest */
-					continue;
-				}
-				if (route->src.ptr)
-				{	/* verify source address, if any */
-					host_t *src = host_create_from_chunk(msg->rtm_family,
-														 route->src, 0);
-					if (src && is_known_vip(this, src))
-					{	/* ignore routes installed by us */
-						src->destroy(src);
-						continue;
-					}
-					route->src_host = src;
-				}
-				/* insert route, sorted by priority and network prefix */
-				enumerator = routes->create_enumerator(routes);
-				while (enumerator->enumerate(enumerator, &other))
-				{
-					if (route->priority < other->priority)
-					{
-						break;
-					}
-					if (route->priority == other->priority &&
-						route->dst_len > other->dst_len)
-					{
-						break;
-					}
-				}
-				routes->insert_before(routes, enumerator, route);
-				enumerator->destroy(enumerator);
-				route = NULL;
-				continue;
-			}
-			default:
-				continue;
-		}
-		break;
-	}
-	if (route)
-	{
-		rt_entry_destroy(route);
-	}
-
-	/* now we have a list of routes matching dest, sorted by net prefix.
-	 * we will look for source addresses for these routes and select the one
-	 * with the preferred source address, if possible */
-	enumerator = routes->create_enumerator(routes);
-	while (enumerator->enumerate(enumerator, &route))
-	{
-		if (route->src_host)
-		{	/* got a source address with the route, if no preferred source
-			 * is given or it matches we are done, as this is the best route */
-			if (!candidate || candidate->ip_equals(candidate, route->src_host))
-			{
-				best = route;
-				break;
-			}
-			else if (route->oif)
-			{	/* no match yet, maybe it is assigned to the same interface */
-				host_t *src = get_interface_address(this, route->oif,
-											msg->rtm_family, dest, candidate);
-				if (src && src->ip_equals(src, candidate))
-				{
-					route->src_host->destroy(route->src_host);
-					route->src_host = src;
-					best = route;
-					break;
-				}
-				DESTROY_IF(src);
-			}
-			/* no luck yet with the source address. if this is the best (first)
-			 * route we store it as fallback in case we don't find a route with
-			 * the preferred source */
-			best = best ?: route;
-			continue;
-		}
-		if (route->oif)
-		{	/* no src, but an interface - get address from it */
-			route->src_host = get_interface_address(this, route->oif,
-											msg->rtm_family, dest, candidate);
-			if (route->src_host)
-			{	/* we handle this address the same as the one above */
-				if (!candidate ||
-					 candidate->ip_equals(candidate, route->src_host))
-				{
-					best = route;
-					break;
-				}
-				best = best ?: route;
-				continue;
-			}
-		}
-		if (route->gtw.ptr)
-		{	/* no src, no iface, but a gateway - lookup src to reach gtw */
-			host_t *gtw;
-
-			gtw = host_create_from_chunk(msg->rtm_family, route->gtw, 0);
-			if (gtw && !gtw->ip_equals(gtw, dest))
-			{
-				route->src_host = get_route(this, gtw, -1, FALSE, candidate,
-											recursion + 1);
-			}
-			DESTROY_IF(gtw);
-			if (route->src_host)
-			{	/* more of the same */
-				if (!candidate ||
-					 candidate->ip_equals(candidate, route->src_host))
-				{
-					best = route;
-					break;
-				}
-				best = best ?: route;
-			}
-		}
-	}
-	enumerator->destroy(enumerator);
-
-	if (nexthop)
-	{	/* nexthop lookup, return gateway if any */
-		if (best || routes->get_first(routes, (void**)&best) == SUCCESS)
-		{
-			addr = host_create_from_chunk(msg->rtm_family, best->gtw, 0);
-		}
-		if (!addr && !match_net)
-		{	/* fallback to destination address */
-			addr = dest->clone(dest);
-		}
-	}
-	else
-	{
-		if (best)
-		{
-			addr = best->src_host->clone(best->src_host);
-		}
-	}
-	this->lock->unlock(this->lock);
-	routes->destroy_function(routes, (void*)rt_entry_destroy);
-	free(out);
-
-	if (addr)
-	{
-		DBG2(DBG_KNL, "using %H as %s to reach %H/%d", addr,
-			 nexthop ? "nexthop" : "address", dest, prefix);
-	}
-	else if (!recursion)
-	{
-		DBG2(DBG_KNL, "no %s found to reach %H/%d",
-			 nexthop ? "nexthop" : "address", dest, prefix);
-	}
-	return addr;
-}
-
-METHOD(kernel_net_t, get_source_addr, host_t*,
-	private_kernel_netlink_net_t *this, host_t *dest, host_t *src)
-{
-	return get_route(this, dest, -1, FALSE, src, 0);
-}
-
-METHOD(kernel_net_t, get_nexthop, host_t*,
-	private_kernel_netlink_net_t *this, host_t *dest, int prefix, host_t *src)
-{
-	return get_route(this, dest, prefix, TRUE, src, 0);
-}
-
-/**
- * Manages the creation and deletion of ip addresses on an interface.
- * By setting the appropriate nlmsg_type, the ip will be set or unset.
- */
-static status_t manage_ipaddr(private_kernel_netlink_net_t *this, int nlmsg_type,
-							  int flags, int if_index, host_t *ip, int prefix)
-{
-	netlink_buf_t request;
-	struct nlmsghdr *hdr;
-	struct ifaddrmsg *msg;
-	chunk_t chunk;
-
-	memset(&request, 0, sizeof(request));
-
-	chunk = ip->get_address(ip);
-
-	hdr = &request.hdr;
-	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
-	hdr->nlmsg_type = nlmsg_type;
-	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
-
-	msg = NLMSG_DATA(hdr);
-	msg->ifa_family = ip->get_family(ip);
-	msg->ifa_flags = 0;
-	msg->ifa_prefixlen = prefix < 0 ? chunk.len * 8 : prefix;
-	msg->ifa_scope = RT_SCOPE_UNIVERSE;
-	msg->ifa_index = if_index;
-
-	netlink_add_attribute(hdr, IFA_LOCAL, chunk, sizeof(request));
-
-	if (ip->get_family(ip) == AF_INET6 && this->rta_prefsrc_for_ipv6)
-	{	/* if source routes are possible we let the virtual IP get deprecated
-		 * immediately (but mark it as valid forever) so it gets only used if
-		 * forced by our route, and not by the default IPv6 address selection */
-		struct ifa_cacheinfo cache = {
-			.ifa_valid = 0xFFFFFFFF,
-			.ifa_prefered = 0,
-		};
-		netlink_add_attribute(hdr, IFA_CACHEINFO, chunk_from_thing(cache),
-							  sizeof(request));
-	}
-	return this->socket->send_ack(this->socket, hdr);
-}
-
-METHOD(kernel_net_t, add_ip, status_t,
-	private_kernel_netlink_net_t *this, host_t *virtual_ip, int prefix,
-	char *iface_name)
-{
-	addr_map_entry_t *entry, lookup = {
-		.ip = virtual_ip,
-	};
-	iface_entry_t *iface = NULL;
-
-	if (!this->install_virtual_ip)
-	{	/* disabled by config */
-		return SUCCESS;
-	}
-
-	this->lock->write_lock(this->lock);
-	/* the virtual IP might actually be installed as regular IP, in which case
-	 * we don't track it as virtual IP */
-	entry = this->addrs->get_match(this->addrs, &lookup,
-								  (void*)addr_map_entry_match);
-	if (!entry)
-	{	/* otherwise it might already be installed as virtual IP */
-		entry = this->vips->get_match(this->vips, &lookup,
-									 (void*)addr_map_entry_match);
-		if (entry)
-		{	/* the vip we found can be in one of three states: 1) installed and
-			 * ready, 2) just added by another thread, but not yet confirmed to
-			 * be installed by the kernel, 3) just deleted, but not yet gone.
-			 * Then while we wait below, several things could happen (as we
-			 * release the lock).  For instance, the interface could disappear,
-			 * or the IP is finally deleted, and it reappears on a different
-			 * interface. All these cases are handled by the call below. */
-			while (!is_vip_installed_or_gone(this, virtual_ip, &entry))
-			{
-				this->condvar->wait(this->condvar, this->lock);
-			}
-			if (entry)
-			{
-				entry->addr->refcount++;
-			}
-		}
-	}
-	if (entry)
-	{
-		DBG2(DBG_KNL, "virtual IP %H is already installed on %s", virtual_ip,
-			 entry->iface->ifname);
-		this->lock->unlock(this->lock);
-		return SUCCESS;
-	}
-	/* try to find the target interface, either by config or via src ip */
-	if (!this->install_virtual_ip_on ||
-		 this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_name,
-						(void**)&iface, this->install_virtual_ip_on) != SUCCESS)
-	{
-		if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_name,
-									 (void**)&iface, iface_name) != SUCCESS)
-		{	/* if we don't find the requested interface we just use the first */
-			this->ifaces->get_first(this->ifaces, (void**)&iface);
-		}
-	}
-	if (iface)
-	{
-		addr_entry_t *addr;
-		char *ifname;
-		int ifi;
-
-		INIT(addr,
-			.ip = virtual_ip->clone(virtual_ip),
-			.refcount = 1,
-			.scope = RT_SCOPE_UNIVERSE,
-		);
-		iface->addrs->insert_last(iface->addrs, addr);
-		addr_map_entry_add(this->vips, addr, iface);
-		ifi = iface->ifindex;
-		this->lock->unlock(this->lock);
-		if (manage_ipaddr(this, RTM_NEWADDR, NLM_F_CREATE | NLM_F_EXCL,
-						  ifi, virtual_ip, prefix) == SUCCESS)
-		{
-			this->lock->write_lock(this->lock);
-			while (!is_vip_installed_or_gone(this, virtual_ip, &entry))
-			{	/* wait until address appears */
-				this->condvar->wait(this->condvar, this->lock);
-			}
-			if (entry)
-			{	/* we fail if the interface got deleted in the meantime */
-				ifname = strdup(entry->iface->ifname);
-				this->lock->unlock(this->lock);
-				DBG2(DBG_KNL, "virtual IP %H installed on %s",
-					 virtual_ip, ifname);
-				/* during IKEv1 reauthentication, children get moved from
-				 * old the new SA before the virtual IP is available. This
-				 * kills the route for our virtual IP, reinstall. */
-				queue_route_reinstall(this, ifname);
-				return SUCCESS;
-			}
-			this->lock->unlock(this->lock);
-		}
-		DBG1(DBG_KNL, "adding virtual IP %H failed", virtual_ip);
-		return FAILED;
-	}
-	this->lock->unlock(this->lock);
-	DBG1(DBG_KNL, "no interface available, unable to install virtual IP %H",
-		 virtual_ip);
-	return FAILED;
-}
-
-METHOD(kernel_net_t, del_ip, status_t,
-	private_kernel_netlink_net_t *this, host_t *virtual_ip, int prefix,
-	bool wait)
-{
-	addr_map_entry_t *entry, lookup = {
-		.ip = virtual_ip,
-	};
-
-	if (!this->install_virtual_ip)
-	{	/* disabled by config */
-		return SUCCESS;
-	}
-
-	DBG2(DBG_KNL, "deleting virtual IP %H", virtual_ip);
-
-	this->lock->write_lock(this->lock);
-	entry = this->vips->get_match(this->vips, &lookup,
-								 (void*)addr_map_entry_match);
-	if (!entry)
-	{	/* we didn't install this IP as virtual IP */
-		entry = this->addrs->get_match(this->addrs, &lookup,
-									  (void*)addr_map_entry_match);
-		if (entry)
-		{
-			DBG2(DBG_KNL, "not deleting existing IP %H on %s", virtual_ip,
-				 entry->iface->ifname);
-			this->lock->unlock(this->lock);
-			return SUCCESS;
-		}
-		DBG2(DBG_KNL, "virtual IP %H not cached, unable to delete", virtual_ip);
-		this->lock->unlock(this->lock);
-		return FAILED;
-	}
-	if (entry->addr->refcount == 1)
-	{
-		status_t status;
-		int ifi;
-
-		/* we set this flag so that threads calling add_ip will block and wait
-		 * until the entry is gone, also so we can wait below */
-		entry->addr->installed = FALSE;
-		ifi = entry->iface->ifindex;
-		this->lock->unlock(this->lock);
-		status = manage_ipaddr(this, RTM_DELADDR, 0, ifi, virtual_ip, prefix);
-		if (status == SUCCESS && wait)
-		{	/* wait until the address is really gone */
-			this->lock->write_lock(this->lock);
-			while (is_known_vip(this, virtual_ip))
-			{
-				this->condvar->wait(this->condvar, this->lock);
-			}
-			this->lock->unlock(this->lock);
-		}
-		return status;
-	}
-	else
-	{
-		entry->addr->refcount--;
-	}
-	DBG2(DBG_KNL, "virtual IP %H used by other SAs, not deleting",
-		 virtual_ip);
-	this->lock->unlock(this->lock);
-	return SUCCESS;
-}
-
-/**
- * Manages source routes in the routing table.
- * By setting the appropriate nlmsg_type, the route gets added or removed.
- */
-static status_t manage_srcroute(private_kernel_netlink_net_t *this,
-								int nlmsg_type, int flags, chunk_t dst_net,
-								u_int8_t prefixlen, host_t *gateway,
-								host_t *src_ip, char *if_name)
-{
-	netlink_buf_t request;
-	struct nlmsghdr *hdr;
-	struct rtmsg *msg;
-	struct rtattr *rta;
-	int ifindex;
-	chunk_t chunk;
-
-	/* if route is 0.0.0.0/0, we can't install it, as it would
-	 * overwrite the default route. Instead, we add two routes:
-	 * 0.0.0.0/1 and 128.0.0.0/1 */
-	if (this->routing_table == 0 && prefixlen == 0)
-	{
-		chunk_t half_net;
-		u_int8_t half_prefixlen;
-		status_t status;
-
-		half_net = chunk_alloca(dst_net.len);
-		memset(half_net.ptr, 0, half_net.len);
-		half_prefixlen = 1;
-
-		status = manage_srcroute(this, nlmsg_type, flags, half_net, half_prefixlen,
-					gateway, src_ip, if_name);
-		half_net.ptr[0] |= 0x80;
-		status = manage_srcroute(this, nlmsg_type, flags, half_net, half_prefixlen,
-					gateway, src_ip, if_name);
-		return status;
-	}
-
-	memset(&request, 0, sizeof(request));
-
-	hdr = &request.hdr;
-	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
-	hdr->nlmsg_type = nlmsg_type;
-	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
-
-	msg = NLMSG_DATA(hdr);
-	msg->rtm_family = src_ip->get_family(src_ip);
-	msg->rtm_dst_len = prefixlen;
-	msg->rtm_table = this->routing_table;
-	msg->rtm_protocol = RTPROT_STATIC;
-	msg->rtm_type = RTN_UNICAST;
-	msg->rtm_scope = RT_SCOPE_UNIVERSE;
-
-	netlink_add_attribute(hdr, RTA_DST, dst_net, sizeof(request));
-	chunk = src_ip->get_address(src_ip);
-	netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request));
-	if (gateway && gateway->get_family(gateway) == src_ip->get_family(src_ip))
-	{
-		chunk = gateway->get_address(gateway);
-		netlink_add_attribute(hdr, RTA_GATEWAY, chunk, sizeof(request));
-	}
-	ifindex = get_interface_index(this, if_name);
-	chunk.ptr = (char*)&ifindex;
-	chunk.len = sizeof(ifindex);
-	netlink_add_attribute(hdr, RTA_OIF, chunk, sizeof(request));
-
-	if (this->mtu || this->mss)
-	{
-		chunk = chunk_alloca(RTA_LENGTH((sizeof(struct rtattr) +
-										 sizeof(u_int32_t)) * 2));
-		chunk.len = 0;
-		rta = (struct rtattr*)chunk.ptr;
-		if (this->mtu)
-		{
-			rta->rta_type = RTAX_MTU;
-			rta->rta_len = RTA_LENGTH(sizeof(u_int32_t));
-			memcpy(RTA_DATA(rta), &this->mtu, sizeof(u_int32_t));
-			chunk.len = rta->rta_len;
-		}
-		if (this->mss)
-		{
-			rta = (struct rtattr*)(chunk.ptr + RTA_ALIGN(chunk.len));
-			rta->rta_type = RTAX_ADVMSS;
-			rta->rta_len = RTA_LENGTH(sizeof(u_int32_t));
-			memcpy(RTA_DATA(rta), &this->mss, sizeof(u_int32_t));
-			chunk.len = RTA_ALIGN(chunk.len) + rta->rta_len;
-		}
-		netlink_add_attribute(hdr, RTA_METRICS, chunk, sizeof(request));
-	}
-
-	return this->socket->send_ack(this->socket, hdr);
-}
-
-METHOD(kernel_net_t, add_route, status_t,
-	private_kernel_netlink_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
-	host_t *gateway, host_t *src_ip, char *if_name)
-{
-	status_t status;
-	route_entry_t *found, route = {
-		.dst_net = dst_net,
-		.prefixlen = prefixlen,
-		.gateway = gateway,
-		.src_ip = src_ip,
-		.if_name = if_name,
-	};
-
-	this->routes_lock->lock(this->routes_lock);
-	found = this->routes->get(this->routes, &route);
-	if (found)
-	{
-		this->routes_lock->unlock(this->routes_lock);
-		return ALREADY_DONE;
-	}
-	status = manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL,
-							 dst_net, prefixlen, gateway, src_ip, if_name);
-	if (status == SUCCESS)
-	{
-		found = route_entry_clone(&route);
-		this->routes->put(this->routes, found, found);
-	}
-	this->routes_lock->unlock(this->routes_lock);
-	return status;
-}
-
-METHOD(kernel_net_t, del_route, status_t,
-	private_kernel_netlink_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
-	host_t *gateway, host_t *src_ip, char *if_name)
-{
-	status_t status;
-	route_entry_t *found, route = {
-		.dst_net = dst_net,
-		.prefixlen = prefixlen,
-		.gateway = gateway,
-		.src_ip = src_ip,
-		.if_name = if_name,
-	};
-
-	this->routes_lock->lock(this->routes_lock);
-	found = this->routes->get(this->routes, &route);
-	if (!found)
-	{
-		this->routes_lock->unlock(this->routes_lock);
-		return NOT_FOUND;
-	}
-	this->routes->remove(this->routes, found);
-	route_entry_destroy(found);
-	status = manage_srcroute(this, RTM_DELROUTE, 0, dst_net, prefixlen,
-							 gateway, src_ip, if_name);
-	this->routes_lock->unlock(this->routes_lock);
-	return status;
-}
-
-/**
- * Initialize a list of local addresses.
- */
-static status_t init_address_list(private_kernel_netlink_net_t *this)
-{
-	netlink_buf_t request;
-	struct nlmsghdr *out, *current, *in;
-	struct rtgenmsg *msg;
-	size_t len;
-	enumerator_t *ifaces, *addrs;
-	iface_entry_t *iface;
-	addr_entry_t *addr;
-
-	DBG2(DBG_KNL, "known interfaces and IP addresses:");
-
-	memset(&request, 0, sizeof(request));
-
-	in = &request.hdr;
-	in->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
-	in->nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT;
-	msg = NLMSG_DATA(in);
-	msg->rtgen_family = AF_UNSPEC;
-
-	/* get all links */
-	in->nlmsg_type = RTM_GETLINK;
-	if (this->socket->send(this->socket, in, &out, &len) != SUCCESS)
-	{
-		return FAILED;
-	}
-	current = out;
-	while (NLMSG_OK(current, len))
-	{
-		switch (current->nlmsg_type)
-		{
-			case NLMSG_DONE:
-				break;
-			case RTM_NEWLINK:
-				process_link(this, current, FALSE);
-				/* fall through */
-			default:
-				current = NLMSG_NEXT(current, len);
-				continue;
-		}
-		break;
-	}
-	free(out);
-
-	/* get all interface addresses */
-	in->nlmsg_type = RTM_GETADDR;
-	if (this->socket->send(this->socket, in, &out, &len) != SUCCESS)
-	{
-		return FAILED;
-	}
-	current = out;
-	while (NLMSG_OK(current, len))
-	{
-		switch (current->nlmsg_type)
-		{
-			case NLMSG_DONE:
-				break;
-			case RTM_NEWADDR:
-				process_addr(this, current, FALSE);
-				/* fall through */
-			default:
-				current = NLMSG_NEXT(current, len);
-				continue;
-		}
-		break;
-	}
-	free(out);
-
-	this->lock->read_lock(this->lock);
-	ifaces = this->ifaces->create_enumerator(this->ifaces);
-	while (ifaces->enumerate(ifaces, &iface))
-	{
-		if (iface_entry_up_and_usable(iface))
-		{
-			DBG2(DBG_KNL, "  %s", iface->ifname);
-			addrs = iface->addrs->create_enumerator(iface->addrs);
-			while (addrs->enumerate(addrs, (void**)&addr))
-			{
-				DBG2(DBG_KNL, "    %H", addr->ip);
-			}
-			addrs->destroy(addrs);
-		}
-	}
-	ifaces->destroy(ifaces);
-	this->lock->unlock(this->lock);
-	return SUCCESS;
-}
-
-/**
- * create or delete a rule to use our routing table
- */
-static status_t manage_rule(private_kernel_netlink_net_t *this, int nlmsg_type,
-							int family, u_int32_t table, u_int32_t prio)
-{
-	netlink_buf_t request;
-	struct nlmsghdr *hdr;
-	struct rtmsg *msg;
-	chunk_t chunk;
-	char *fwmark;
-
-	memset(&request, 0, sizeof(request));
-	hdr = &request.hdr;
-	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
-	hdr->nlmsg_type = nlmsg_type;
-	if (nlmsg_type == RTM_NEWRULE)
-	{
-		hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
-	}
-	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
-
-	msg = NLMSG_DATA(hdr);
-	msg->rtm_table = table;
-	msg->rtm_family = family;
-	msg->rtm_protocol = RTPROT_BOOT;
-	msg->rtm_scope = RT_SCOPE_UNIVERSE;
-	msg->rtm_type = RTN_UNICAST;
-
-	chunk = chunk_from_thing(prio);
-	netlink_add_attribute(hdr, RTA_PRIORITY, chunk, sizeof(request));
-
-	fwmark = lib->settings->get_str(lib->settings,
-							"%s.plugins.kernel-netlink.fwmark", NULL, lib->ns);
-	if (fwmark)
-	{
-#ifdef HAVE_LINUX_FIB_RULES_H
-		mark_t mark;
-
-		if (fwmark[0] == '!')
-		{
-			msg->rtm_flags |= FIB_RULE_INVERT;
-			fwmark++;
-		}
-		if (mark_from_string(fwmark, &mark))
-		{
-			chunk = chunk_from_thing(mark.value);
-			netlink_add_attribute(hdr, FRA_FWMARK, chunk, sizeof(request));
-			chunk = chunk_from_thing(mark.mask);
-			netlink_add_attribute(hdr, FRA_FWMASK, chunk, sizeof(request));
-			if (msg->rtm_flags & FIB_RULE_INVERT)
-			{
-				this->routing_mark = mark;
-			}
-		}
-#else
-		DBG1(DBG_KNL, "setting firewall mark on routing rule is not supported");
-#endif
-	}
-	return this->socket->send_ack(this->socket, hdr);
-}
-
-/**
- * check for kernel features (currently only via version number)
- */
-static void check_kernel_features(private_kernel_netlink_net_t *this)
-{
-	struct utsname utsname;
-	int a, b, c;
-
-	if (uname(&utsname) == 0)
-	{
-		switch(sscanf(utsname.release, "%d.%d.%d", &a, &b, &c))
-		{
-			case 3:
-				if (a == 2)
-				{
-					if (b == 6 && c >= 36)
-					{
-						this->rta_mark = TRUE;
-					}
-					DBG2(DBG_KNL, "detected Linux %d.%d.%d, no support for "
-						 "RTA_PREFSRC for IPv6 routes", a, b, c);
-					break;
-				}
-				/* fall-through */
-			case 2:
-				/* only 3.x+ uses two part version numbers */
-				this->rta_prefsrc_for_ipv6 = TRUE;
-				this->rta_mark = TRUE;
-				break;
-			default:
-				break;
-		}
-	}
-}
-
-/**
- * Destroy an address to iface map
- */
-static void addr_map_destroy(hashtable_t *map)
-{
-	enumerator_t *enumerator;
-	addr_map_entry_t *addr;
-
-	enumerator = map->create_enumerator(map);
-	while (enumerator->enumerate(enumerator, NULL, (void**)&addr))
-	{
-		free(addr);
-	}
-	enumerator->destroy(enumerator);
-	map->destroy(map);
-}
-
-METHOD(kernel_net_t, destroy, void,
-	private_kernel_netlink_net_t *this)
-{
-	enumerator_t *enumerator;
-	route_entry_t *route;
-
-	if (this->routing_table)
-	{
-		manage_rule(this, RTM_DELRULE, AF_INET, this->routing_table,
-					this->routing_table_prio);
-		manage_rule(this, RTM_DELRULE, AF_INET6, this->routing_table,
-					this->routing_table_prio);
-	}
-	if (this->socket_events > 0)
-	{
-		lib->watcher->remove(lib->watcher, this->socket_events);
-		close(this->socket_events);
-	}
-	enumerator = this->routes->create_enumerator(this->routes);
-	while (enumerator->enumerate(enumerator, NULL, (void**)&route))
-	{
-		manage_srcroute(this, RTM_DELROUTE, 0, route->dst_net, route->prefixlen,
-						route->gateway, route->src_ip, route->if_name);
-		route_entry_destroy(route);
-	}
-	enumerator->destroy(enumerator);
-	this->routes->destroy(this->routes);
-	this->routes_lock->destroy(this->routes_lock);
-	DESTROY_IF(this->socket);
-
-	net_changes_clear(this);
-	this->net_changes->destroy(this->net_changes);
-	this->net_changes_lock->destroy(this->net_changes_lock);
-
-	addr_map_destroy(this->addrs);
-	addr_map_destroy(this->vips);
-
-	this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
-	this->rt_exclude->destroy(this->rt_exclude);
-	this->roam_lock->destroy(this->roam_lock);
-	this->condvar->destroy(this->condvar);
-	this->lock->destroy(this->lock);
-	free(this);
-}
-
-/*
- * Described in header.
- */
-kernel_netlink_net_t *kernel_netlink_net_create()
-{
-	private_kernel_netlink_net_t *this;
-	enumerator_t *enumerator;
-	bool register_for_events = TRUE;
-	char *exclude;
-
-	INIT(this,
-		.public = {
-			.interface = {
-				.get_interface = _get_interface_name,
-				.create_address_enumerator = _create_address_enumerator,
-				.get_source_addr = _get_source_addr,
-				.get_nexthop = _get_nexthop,
-				.add_ip = _add_ip,
-				.del_ip = _del_ip,
-				.add_route = _add_route,
-				.del_route = _del_route,
-				.destroy = _destroy,
-			},
-		},
-		.socket = netlink_socket_create(NETLINK_ROUTE, rt_msg_names,
-			lib->settings->get_bool(lib->settings,
-				"%s.plugins.kernel-netlink.parallel_route", FALSE, lib->ns)),
-		.rt_exclude = linked_list_create(),
-		.routes = hashtable_create((hashtable_hash_t)route_entry_hash,
-								   (hashtable_equals_t)route_entry_equals, 16),
-		.net_changes = hashtable_create(
-								   (hashtable_hash_t)net_change_hash,
-								   (hashtable_equals_t)net_change_equals, 16),
-		.addrs = hashtable_create(
-								(hashtable_hash_t)addr_map_entry_hash,
-								(hashtable_equals_t)addr_map_entry_equals, 16),
-		.vips = hashtable_create((hashtable_hash_t)addr_map_entry_hash,
-								 (hashtable_equals_t)addr_map_entry_equals, 16),
-		.routes_lock = mutex_create(MUTEX_TYPE_DEFAULT),
-		.net_changes_lock = mutex_create(MUTEX_TYPE_DEFAULT),
-		.ifaces = linked_list_create(),
-		.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
-		.condvar = rwlock_condvar_create(),
-		.roam_lock = spinlock_create(),
-		.routing_table = lib->settings->get_int(lib->settings,
-						"%s.routing_table", ROUTING_TABLE, lib->ns),
-		.routing_table_prio = lib->settings->get_int(lib->settings,
-						"%s.routing_table_prio", ROUTING_TABLE_PRIO, lib->ns),
-		.process_route = lib->settings->get_bool(lib->settings,
-						"%s.process_route", TRUE, lib->ns),
-		.install_virtual_ip = lib->settings->get_bool(lib->settings,
-						"%s.install_virtual_ip", TRUE, lib->ns),
-		.install_virtual_ip_on = lib->settings->get_str(lib->settings,
-						"%s.install_virtual_ip_on", NULL, lib->ns),
-		.prefer_temporary_addrs = lib->settings->get_bool(lib->settings,
-						"%s.prefer_temporary_addrs", FALSE, lib->ns),
-		.roam_events = lib->settings->get_bool(lib->settings,
-						"%s.plugins.kernel-netlink.roam_events", TRUE, lib->ns),
-		.mtu = lib->settings->get_int(lib->settings,
-						"%s.plugins.kernel-netlink.mtu", 0, lib->ns),
-		.mss = lib->settings->get_int(lib->settings,
-						"%s.plugins.kernel-netlink.mss", 0, lib->ns),
-	);
-	timerclear(&this->last_route_reinstall);
-	timerclear(&this->next_roam);
-
-	check_kernel_features(this);
-
-	if (streq(lib->ns, "starter"))
-	{	/* starter has no threads, so we do not register for kernel events */
-		register_for_events = FALSE;
-	}
-
-	exclude = lib->settings->get_str(lib->settings,
-									 "%s.ignore_routing_tables", NULL, lib->ns);
-	if (exclude)
-	{
-		char *token;
-		uintptr_t table;
-
-		enumerator = enumerator_create_token(exclude, " ", " ");
-		while (enumerator->enumerate(enumerator, &token))
-		{
-			errno = 0;
-			table = strtoul(token, NULL, 10);
-
-			if (errno == 0)
-			{
-				this->rt_exclude->insert_last(this->rt_exclude, (void*)table);
-			}
-		}
-		enumerator->destroy(enumerator);
-	}
-
-	if (register_for_events)
-	{
-		struct sockaddr_nl addr;
-
-		memset(&addr, 0, sizeof(addr));
-		addr.nl_family = AF_NETLINK;
-
-		/* create and bind RT socket for events (address/interface/route changes) */
-		this->socket_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
-		if (this->socket_events < 0)
-		{
-			DBG1(DBG_KNL, "unable to create RT event socket");
-			destroy(this);
-			return NULL;
-		}
-		addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |
-						 RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_LINK;
-		if (bind(this->socket_events, (struct sockaddr*)&addr, sizeof(addr)))
-		{
-			DBG1(DBG_KNL, "unable to bind RT event socket");
-			destroy(this);
-			return NULL;
-		}
-
-		lib->watcher->add(lib->watcher, this->socket_events, WATCHER_READ,
-						  (watcher_cb_t)receive_events, this);
-	}
-
-	if (init_address_list(this) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to get interface list");
-		destroy(this);
-		return NULL;
-	}
-
-	if (this->routing_table)
-	{
-		if (manage_rule(this, RTM_NEWRULE, AF_INET, this->routing_table,
-						this->routing_table_prio) != SUCCESS)
-		{
-			DBG1(DBG_KNL, "unable to create IPv4 routing table rule");
-		}
-		if (manage_rule(this, RTM_NEWRULE, AF_INET6, this->routing_table,
-						this->routing_table_prio) != SUCCESS)
-		{
-			DBG1(DBG_KNL, "unable to create IPv6 routing table rule");
-		}
-	}
-
-	return &this->public;
-}
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.c
deleted file mode 100644
index 8d5a0d5..0000000
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.
- */
-
-
-#include "kernel_netlink_plugin.h"
-
-#include "kernel_netlink_ipsec.h"
-#include "kernel_netlink_net.h"
-
-#include <hydra.h>
-
-typedef struct private_kernel_netlink_plugin_t private_kernel_netlink_plugin_t;
-
-/**
- * private data of kernel netlink plugin
- */
-struct private_kernel_netlink_plugin_t {
-	/**
-	 * implements plugin interface
-	 */
-	kernel_netlink_plugin_t public;
-};
-
-METHOD(plugin_t, get_name, char*,
-	private_kernel_netlink_plugin_t *this)
-{
-	return "kernel-netlink";
-}
-
-METHOD(plugin_t, get_features, int,
-	private_kernel_netlink_plugin_t *this, plugin_feature_t *features[])
-{
-	static plugin_feature_t f[] = {
-		PLUGIN_CALLBACK(kernel_ipsec_register, kernel_netlink_ipsec_create),
-			PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"),
-		PLUGIN_CALLBACK(kernel_net_register, kernel_netlink_net_create),
-			PLUGIN_PROVIDE(CUSTOM, "kernel-net"),
-	};
-	*features = f;
-	return countof(f);
-}
-
-METHOD(plugin_t, destroy, void,
-	private_kernel_netlink_plugin_t *this)
-{
-	free(this);
-}
-
-/*
- * see header file
- */
-plugin_t *kernel_netlink_plugin_create()
-{
-	private_kernel_netlink_plugin_t *this;
-
-	if (!lib->caps->keep(lib->caps, CAP_NET_ADMIN))
-	{	/* required to bind/use XFRM sockets / create/modify routing tables, but
-		 * not if only the read-only parts of kernel-netlink-net are used, so
-		 * we don't fail here */
-		DBG1(DBG_KNL, "kernel-netlink plugin might require CAP_NET_ADMIN "
-			 "capability");
-	}
-
-	INIT(this,
-		.public = {
-			.plugin = {
-				.get_name = _get_name,
-				.get_features = _get_features,
-				.destroy = _destroy,
-			},
-		},
-	);
-
-	return &this->public.plugin;
-}
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.h b/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.h
deleted file mode 100644
index a795486..0000000
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @defgroup kernel_netlink kernel_netlink
- * @ingroup hplugins
- *
- * @defgroup kernel_netlink_plugin kernel_netlink_plugin
- * @{ @ingroup kernel_netlink
- */
-
-#ifndef KERNEL_NETLINK_PLUGIN_H_
-#define KERNEL_NETLINK_PLUGIN_H_
-
-#include <plugins/plugin.h>
-
-typedef struct kernel_netlink_plugin_t kernel_netlink_plugin_t;
-
-/**
- * netlink kernel interface plugin
- */
-struct kernel_netlink_plugin_t {
-
-	/**
-	 * implements plugin interface
-	 */
-	plugin_t plugin;
-};
-
-#endif /** KERNEL_NETLINK_PLUGIN_H_ @}*/
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.h b/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.h
deleted file mode 100644
index 6668290..0000000
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef KERNEL_NETLINK_SHARED_H_
-#define KERNEL_NETLINK_SHARED_H_
-
-#include <library.h>
-
-#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 union {
-	struct nlmsghdr hdr;
-	u_char bytes[1024];
-} netlink_buf_t __attribute__((aligned(RTA_ALIGNTO)));
-
-typedef struct netlink_socket_t netlink_socket_t;
-
-/**
- * Wrapper around a netlink socket.
- */
-struct netlink_socket_t {
-
-	/**
-	 * Send a netlink message and wait for a reply.
-	 *
-	 * @param	in		netlink message to send
-	 * @param	out 	received netlink message
-	 * @param	out_len	length of the received message
-	 */
-	status_t (*send)(netlink_socket_t *this, struct nlmsghdr *in,
-					 struct nlmsghdr **out, size_t *out_len);
-
-	/**
-	 * Send a netlink message and wait for its acknowledge.
-	 *
-	 * @param	in		netlink message to send
-	 */
-	status_t (*send_ack)(netlink_socket_t *this, struct nlmsghdr *in);
-
-	/**
-	 * Destroy the socket.
-	 */
-	void (*destroy)(netlink_socket_t *this);
-};
-
-/**
- * Create a netlink_socket_t object.
- *
- * @param protocol	protocol type (e.g. NETLINK_XFRM or NETLINK_ROUTE)
- * @param names		optional enum names for Netlink messages
- * @param parallel	support parallel queries on this Netlink socket
- */
-netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names,
-										bool parallel);
-
-/**
- * Creates an rtattr and adds it to the given netlink message.
- *
- * @param hdr			netlink message
- * @param rta_type		type of the rtattr
- * @param data			data to add to the rtattr
- * @param buflen		length of the netlink message buffer
- */
-void netlink_add_attribute(struct nlmsghdr *hdr, int rta_type, chunk_t data,
-						   size_t buflen);
-
-/**
- * Reserve space in a netlink message for given size and type, returning buffer.
- *
- * @param hdr			netlink message
- * @param buflen		size of full netlink buffer
- * @param type			RTA type
- * @param len			length of RTA data
- * @return				buffer to len bytes of attribute data, NULL on error
- */
-void* netlink_reserve(struct nlmsghdr *hdr, int buflen, int type, int len);
-
-#endif /* KERNEL_NETLINK_SHARED_H_ */
diff --git a/src/libhydra/plugins/kernel_netlink/tests.c b/src/libhydra/plugins/kernel_netlink/tests.c
deleted file mode 100644
index 52985b4..0000000
--- a/src/libhydra/plugins/kernel_netlink/tests.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2014 Martin Willi
- * Copyright (C) 2014 revosec AG
- *
- * 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.
- */
-
-#include <test_runner.h>
-
-#include <hydra.h>
-
-/* declare test suite constructors */
-#define TEST_SUITE(x) test_suite_t* x();
-#include "tests.h"
-#undef TEST_SUITE
-
-static test_configuration_t tests[] = {
-#define TEST_SUITE(x) \
-	{ .suite = x, },
-#include "tests.h"
-	{ .suite = NULL, }
-};
-
-static bool test_runner_init(bool init)
-{
-	if (init)
-	{
-		lib->processor->set_threads(lib->processor, 8);
-	}
-	else
-	{
-		lib->processor->set_threads(lib->processor, 0);
-		lib->processor->cancel(lib->processor);
-	}
-	return TRUE;
-}
-
-int main(int argc, char *argv[])
-{
-	return test_runner_run("kernel-netlink", tests, test_runner_init);
-}
diff --git a/src/libhydra/plugins/kernel_pfkey/Makefile.am b/src/libhydra/plugins/kernel_pfkey/Makefile.am
deleted file mode 100644
index f645528..0000000
--- a/src/libhydra/plugins/kernel_pfkey/Makefile.am
+++ /dev/null
@@ -1,19 +0,0 @@
-AM_CPPFLAGS = \
-	-I${linux_headers} \
-	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra
-
-AM_CFLAGS = \
-	$(PLUGIN_CFLAGS)
-
-if MONOLITHIC
-noinst_LTLIBRARIES = libstrongswan-kernel-pfkey.la
-else
-plugin_LTLIBRARIES = libstrongswan-kernel-pfkey.la
-endif
-
-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 -avoid-version
diff --git a/src/libhydra/plugins/kernel_pfkey/Makefile.in b/src/libhydra/plugins/kernel_pfkey/Makefile.in
deleted file mode 100644
index 177d2f2..0000000
--- a/src/libhydra/plugins/kernel_pfkey/Makefile.in
+++ /dev/null
@@ -1,780 +0,0 @@
-# Makefile.in generated by automake 1.14.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 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.
-
- at SET_MAKE@
-
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
-  case $${target_option-} in \
-      ?) ;; \
-      *) echo "am__make_running_with_option: internal error: invalid" \
-              "target option '$${target_option-}' specified" >&2; \
-         exit 1;; \
-  esac; \
-  has_opt=no; \
-  sane_makeflags=$$MAKEFLAGS; \
-  if $(am__is_gnu_make); then \
-    sane_makeflags=$$MFLAGS; \
-  else \
-    case $$MAKEFLAGS in \
-      *\\[\ \	]*) \
-        bs=\\; \
-        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
-          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
-    esac; \
-  fi; \
-  skip_next=no; \
-  strip_trailopt () \
-  { \
-    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
-  }; \
-  for flg in $$sane_makeflags; do \
-    test $$skip_next = yes && { skip_next=no; continue; }; \
-    case $$flg in \
-      *=*|--*) continue;; \
-        -*I) strip_trailopt 'I'; skip_next=yes;; \
-      -*I?*) strip_trailopt 'I';; \
-        -*O) strip_trailopt 'O'; skip_next=yes;; \
-      -*O?*) strip_trailopt 'O';; \
-        -*l) strip_trailopt 'l'; skip_next=yes;; \
-      -*l?*) strip_trailopt 'l';; \
-      -[dEDm]) skip_next=yes;; \
-      -[JT]) skip_next=yes;; \
-    esac; \
-    case $$flg in \
-      *$$target_option*) has_opt=yes; break;; \
-    esac; \
-  done; \
-  test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@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/libhydra/plugins/kernel_pfkey
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
-	$(top_srcdir)/depcomp
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
-	$(top_srcdir)/m4/config/ltoptions.m4 \
-	$(top_srcdir)/m4/config/ltsugar.m4 \
-	$(top_srcdir)/m4/config/ltversion.m4 \
-	$(top_srcdir)/m4/config/lt~obsolete.m4 \
-	$(top_srcdir)/m4/macros/split-package-version.m4 \
-	$(top_srcdir)/m4/macros/with.m4 \
-	$(top_srcdir)/m4/macros/enable-disable.m4 \
-	$(top_srcdir)/m4/macros/add-plugin.m4 \
-	$(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-	$(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_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 = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
-  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
-  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
-  for p in $$list; do echo "$$p $$p"; done | \
-  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
-  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
-    if (++n[$$2] == $(am__install_max)) \
-      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
-    END { for (dir in files) print dir, files[dir] }'
-am__base_list = \
-  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
-  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__uninstall_files_from_dir = { \
-  test -z "$$files" \
-    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
-    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
-         $(am__cd) "$$dir" && rm -f $$files; }; \
-  }
-am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(noinst_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)
-AM_V_lt = $(am__v_lt_ at AM_V@)
-am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 = 
-libstrongswan_kernel_pfkey_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
-	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
-	$(AM_CFLAGS) $(CFLAGS) \
-	$(libstrongswan_kernel_pfkey_la_LDFLAGS) $(LDFLAGS) -o $@
- at MONOLITHIC_FALSE@am_libstrongswan_kernel_pfkey_la_rpath = -rpath \
- at MONOLITHIC_FALSE@	$(plugindir)
- at MONOLITHIC_TRUE@am_libstrongswan_kernel_pfkey_la_rpath =
-AM_V_P = $(am__v_P_ at AM_V@)
-am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_ at AM_V@)
-am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 = 
-AM_V_at = $(am__v_at_ at AM_V@)
-am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 = 
-DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-	$(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_ at AM_V@)
-am__v_CC_ = $(am__v_CC_ at AM_DEFAULT_V@)
-am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 = 
-CCLD = $(CC)
-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-	$(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_ at AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_ at AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo "  CCLD    " $@;
-am__v_CCLD_1 = 
-SOURCES = $(libstrongswan_kernel_pfkey_la_SOURCES)
-DIST_SOURCES = $(libstrongswan_kernel_pfkey_la_SOURCES)
-am__can_run_installinfo = \
-  case $$AM_UPDATE_INFO_DIR in \
-    n|no|NO) false;; \
-    *) (install-info --version) >/dev/null 2>&1;; \
-  esac
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates.  Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
-  BEGIN { nonempty = 0; } \
-  { items[$$0] = 1; nonempty = 1; } \
-  END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique.  This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
-  list='$(am__tagged_files)'; \
-  unique=`for i in $$list; do \
-    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-  done | $(am__uniquify_input)`
-ETAGS = etags
-CTAGS = ctags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-ALLOCA = @ALLOCA@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BFDLIB = @BFDLIB@
-BTLIB = @BTLIB@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
-COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLIB = @DLLIB@
-DLLTOOL = @DLLTOOL@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-EASY_INSTALL = @EASY_INSTALL@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FGREP = @FGREP@
-GEM = @GEM@
-GENHTML = @GENHTML@
-GPERF = @GPERF@
-GPRBUILD = @GPRBUILD@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LCOV = @LCOV@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LEX = @LEX@
-LEXLIB = @LEXLIB@
-LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-MYSQLCFLAG = @MYSQLCFLAG@
-MYSQLCONFIG = @MYSQLCONFIG@
-MYSQLLIB = @MYSQLLIB@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OPENSSL_LIB = @OPENSSL_LIB@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
-PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
-PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
-PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PERL = @PERL@
-PKG_CONFIG = @PKG_CONFIG@
-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
-PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
-PTHREADLIB = @PTHREADLIB@
-PYTHON = @PYTHON@
-PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
-PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
-PYTHON_PLATFORM = @PYTHON_PLATFORM@
-PYTHON_PREFIX = @PYTHON_PREFIX@
-PYTHON_VERSION = @PYTHON_VERSION@
-PY_TEST = @PY_TEST@
-RANLIB = @RANLIB@
-RTLIB = @RTLIB@
-RUBY = @RUBY@
-RUBYGEMDIR = @RUBYGEMDIR@
-RUBYINCLUDE = @RUBYINCLUDE@
-RUBYLIB = @RUBYLIB@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-SOCKLIB = @SOCKLIB@
-STRIP = @STRIP@
-UNWINDLIB = @UNWINDLIB@
-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_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-aikgen_plugins = @aikgen_plugins@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-attest_plugins = @attest_plugins@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-c_plugins = @c_plugins@
-charon_natt_port = @charon_natt_port@
-charon_plugins = @charon_plugins@
-charon_udp_port = @charon_udp_port@
-clearsilver_LIBS = @clearsilver_LIBS@
-cmd_plugins = @cmd_plugins@
-datadir = @datadir@
-datarootdir = @datarootdir@
-dbusservicedir = @dbusservicedir@
-dev_headers = @dev_headers@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-fips_mode = @fips_mode@
-gtk_CFLAGS = @gtk_CFLAGS@
-gtk_LIBS = @gtk_LIBS@
-h_plugins = @h_plugins@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-imcvdir = @imcvdir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-ipsec_script = @ipsec_script@
-ipsec_script_upper = @ipsec_script_upper@
-ipsecdir = @ipsecdir@
-ipsecgroup = @ipsecgroup@
-ipseclibdir = @ipseclibdir@
-ipsecuser = @ipsecuser@
-json_CFLAGS = @json_CFLAGS@
-json_LIBS = @json_LIBS@
-libdir = @libdir@
-libexecdir = @libexecdir@
-libiptc_CFLAGS = @libiptc_CFLAGS@
-libiptc_LIBS = @libiptc_LIBS@
-linux_headers = @linux_headers@
-localedir = @localedir@
-localstatedir = @localstatedir@
-maemo_CFLAGS = @maemo_CFLAGS@
-maemo_LIBS = @maemo_LIBS@
-manager_plugins = @manager_plugins@
-mandir = @mandir@
-medsrv_plugins = @medsrv_plugins@
-mkdir_p = @mkdir_p@
-nm_CFLAGS = @nm_CFLAGS@
-nm_LIBS = @nm_LIBS@
-nm_ca_dir = @nm_ca_dir@
-nm_plugins = @nm_plugins@
-oldincludedir = @oldincludedir@
-pcsclite_CFLAGS = @pcsclite_CFLAGS@
-pcsclite_LIBS = @pcsclite_LIBS@
-pdfdir = @pdfdir@
-piddir = @piddir@
-pkgpyexecdir = @pkgpyexecdir@
-pkgpythondir = @pkgpythondir@
-pki_plugins = @pki_plugins@
-plugindir = @plugindir@
-pool_plugins = @pool_plugins@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-pyexecdir = @pyexecdir@
-pythondir = @pythondir@
-random_device = @random_device@
-resolv_conf = @resolv_conf@
-routing_table = @routing_table@
-routing_table_prio = @routing_table_prio@
-s_plugins = @s_plugins@
-sbindir = @sbindir@
-scepclient_plugins = @scepclient_plugins@
-scripts_plugins = @scripts_plugins@
-sharedstatedir = @sharedstatedir@
-soup_CFLAGS = @soup_CFLAGS@
-soup_LIBS = @soup_LIBS@
-srcdir = @srcdir@
-starter_plugins = @starter_plugins@
-strongswan_conf = @strongswan_conf@
-strongswan_options = @strongswan_options@
-swanctldir = @swanctldir@
-sysconfdir = @sysconfdir@
-systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
-systemd_daemon_LIBS = @systemd_daemon_LIBS@
-systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
-systemd_journal_LIBS = @systemd_journal_LIBS@
-systemdsystemunitdir = @systemdsystemunitdir@
-t_plugins = @t_plugins@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-urandom_device = @urandom_device@
-xml_CFLAGS = @xml_CFLAGS@
-xml_LIBS = @xml_LIBS@
-AM_CPPFLAGS = \
-	-I${linux_headers} \
-	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra
-
-AM_CFLAGS = \
-	$(PLUGIN_CFLAGS)
-
- at MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-kernel-pfkey.la
- at MONOLITHIC_FALSE@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 -avoid-version
-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 ) \
-	        && { if test -f $@; then exit 0; else break; fi; }; \
-	      exit 1;; \
-	  esac; \
-	done; \
-	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libhydra/plugins/kernel_pfkey/Makefile'; \
-	$(am__cd) $(top_srcdir) && \
-	  $(AUTOMAKE) --gnu src/libhydra/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
-$(am__aclocal_m4_deps):
-
-clean-noinstLTLIBRARIES:
-	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-	@list='$(noinst_LTLIBRARIES)'; \
-	locs=`for p in $$list; do echo $$p; done | \
-	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
-	      sort -u`; \
-	test -z "$$locs" || { \
-	  echo rm -f $${locs}; \
-	  rm -f $${locs}; \
-	}
-
-install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
-	@$(NORMAL_INSTALL)
-	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
-	list2=; for p in $$list; do \
-	  if test -f $$p; then \
-	    list2="$$list2 $$p"; \
-	  else :; fi; \
-	done; \
-	test -z "$$list2" || { \
-	  echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
-	  $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
-	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
-	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
-	}
-
-uninstall-pluginLTLIBRARIES:
-	@$(NORMAL_UNINSTALL)
-	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
-	for p in $$list; do \
-	  $(am__strip_dir) \
-	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
-	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
-	done
-
-clean-pluginLTLIBRARIES:
-	-test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
-	@list='$(plugin_LTLIBRARIES)'; \
-	locs=`for p in $$list; do echo $$p; done | \
-	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
-	      sort -u`; \
-	test -z "$$locs" || { \
-	  echo rm -f $${locs}; \
-	  rm -f $${locs}; \
-	}
-
-libstrongswan-kernel-pfkey.la: $(libstrongswan_kernel_pfkey_la_OBJECTS) $(libstrongswan_kernel_pfkey_la_DEPENDENCIES) $(EXTRA_libstrongswan_kernel_pfkey_la_DEPENDENCIES) 
-	$(AM_V_CCLD)$(libstrongswan_kernel_pfkey_la_LINK) $(am_libstrongswan_kernel_pfkey_la_rpath) $(libstrongswan_kernel_pfkey_la_OBJECTS) $(libstrongswan_kernel_pfkey_la_LIBADD) $(LIBS)
-
-mostlyclean-compile:
-	-rm -f *.$(OBJEXT)
-
-distclean-compile:
-	-rm -f *.tab.c
-
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_pfkey_ipsec.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_pfkey_plugin.Plo at am__quote@
-
-.c.o:
- at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
- at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
- at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ $<
-
-.c.obj:
- at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
- at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
- at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-
-.c.lo:
- at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
- at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
- at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LTCOMPILE) -c -o $@ $<
-
-mostlyclean-libtool:
-	-rm -f *.lo
-
-clean-libtool:
-	-rm -rf .libs _libs
-
-ID: $(am__tagged_files)
-	$(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-am
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-	set x; \
-	here=`pwd`; \
-	$(am__define_uniq_tagged_files); \
-	shift; \
-	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-	  test -n "$$unique" || unique=$$empty_fix; \
-	  if test $$# -gt 0; then \
-	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-	      "$$@" $$unique; \
-	  else \
-	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-	      $$unique; \
-	  fi; \
-	fi
-ctags: ctags-am
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-	$(am__define_uniq_tagged_files); \
-	test -z "$(CTAGS_ARGS)$$unique" \
-	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-	     $$unique
-
-GTAGS:
-	here=`$(am__cd) $(top_builddir) && pwd` \
-	  && $(am__cd) $(top_srcdir) \
-	  && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-am
-
-cscopelist-am: $(am__tagged_files)
-	list='$(am__tagged_files)'; \
-	case "$(srcdir)" in \
-	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
-	  *) sdir=$(subdir)/$(srcdir) ;; \
-	esac; \
-	for i in $$list; do \
-	  if test -f "$$i"; then \
-	    echo "$(subdir)/$$i"; \
-	  else \
-	    echo "$$sdir/$$i"; \
-	  fi; \
-	done >> $(top_builddir)/cscope.files
-
-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 "$(distdir)/$$file"; then \
-	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-	    fi; \
-	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-	    fi; \
-	    cp -fpR $$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:
-	if test -z '$(STRIP)'; then \
-	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-	      install; \
-	else \
-	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-	fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
-	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-noinstLTLIBRARIES \
-	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
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am: install-pluginLTLIBRARIES
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-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 TAGS all all-am check check-am clean clean-generic \
-	clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
-	cscopelist-am ctags ctags-am 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 tags-am 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/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
deleted file mode 100644
index a2fccd1..0000000
--- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
+++ /dev/null
@@ -1,3102 +0,0 @@
-/*
- * Copyright (C) 2008-2015 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.
- */
-/*
- * Copyright (C) 2014 Nanoteq Pty Ltd
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#ifdef __FreeBSD__
-#include <limits.h> /* for LONG_MAX */
-#endif
-
-#ifdef HAVE_NET_PFKEYV2_H
-#include <net/pfkeyv2.h>
-#else
-#include <linux/pfkeyv2.h>
-#endif
-
-#ifdef SADB_X_EXT_NAT_T_TYPE
-#define HAVE_NATT
-#endif
-
-#ifdef HAVE_NETIPSEC_IPSEC_H
-#include <netipsec/ipsec.h>
-#elif defined(HAVE_NETINET6_IPSEC_H)
-#include <netinet6/ipsec.h>
-#else
-#include <linux/ipsec.h>
-#endif
-
-#ifdef HAVE_NATT
-#ifdef HAVE_LINUX_UDP_H
-#include <linux/udp.h>
-#else
-#include <netinet/udp.h>
-#endif /*HAVE_LINUX_UDP_H*/
-#endif /*HAVE_NATT*/
-
-#include <unistd.h>
-#include <time.h>
-#include <errno.h>
-#ifdef __APPLE__
-#include <sys/sysctl.h>
-#endif
-
-#include "kernel_pfkey_ipsec.h"
-
-#include <hydra.h>
-#include <utils/debug.h>
-#include <networking/host.h>
-#include <collections/linked_list.h>
-#include <collections/hashtable.h>
-#include <threading/mutex.h>
-
-/** non linux specific */
-#ifndef IPPROTO_COMP
-#ifdef IPPROTO_IPCOMP
-#define IPPROTO_COMP IPPROTO_IPCOMP
-#endif
-#endif
-
-#ifndef SADB_X_AALG_SHA2_256HMAC
-#define SADB_X_AALG_SHA2_256HMAC SADB_X_AALG_SHA2_256
-#define SADB_X_AALG_SHA2_384HMAC SADB_X_AALG_SHA2_384
-#define SADB_X_AALG_SHA2_512HMAC SADB_X_AALG_SHA2_512
-#endif
-
-#ifndef SADB_X_EALG_AESCBC
-#define SADB_X_EALG_AESCBC SADB_X_EALG_AES
-#endif
-
-#ifndef SADB_X_EALG_CASTCBC
-#define SADB_X_EALG_CASTCBC SADB_X_EALG_CAST128CBC
-#endif
-
-#if !defined(SADB_X_EALG_AES_GCM_ICV8) && defined(SADB_X_EALG_AESGCM8)
-#define SADB_X_EALG_AES_GCM_ICV8 SADB_X_EALG_AESGCM8
-#define SADB_X_EALG_AES_GCM_ICV12 SADB_X_EALG_AESGCM12
-#define SADB_X_EALG_AES_GCM_ICV16 SADB_X_EALG_AESGCM16
-#endif
-
-#ifndef SOL_IP
-#define SOL_IP IPPROTO_IP
-#define SOL_IPV6 IPPROTO_IPV6
-#endif
-
-/** from linux/in.h */
-#ifndef IP_IPSEC_POLICY
-#define IP_IPSEC_POLICY 16
-#endif
-
-/** missing on uclibc */
-#ifndef IPV6_IPSEC_POLICY
-#define IPV6_IPSEC_POLICY 34
-#endif
-
-/* from linux/udp.h */
-#ifndef UDP_ENCAP
-#define UDP_ENCAP 100
-#endif
-
-#ifndef UDP_ENCAP_ESPINUDP
-#define UDP_ENCAP_ESPINUDP 2
-#endif
-
-/* this is not defined on some platforms */
-#ifndef SOL_UDP
-#define SOL_UDP IPPROTO_UDP
-#endif
-
-/** base priority for installed policies */
-#define PRIO_BASE 384
-
-#ifdef __APPLE__
-/** from xnu/bsd/net/pfkeyv2.h */
-#define SADB_X_EXT_NATT 0x002
-	struct sadb_sa_2 {
-		struct sadb_sa	sa;
-		u_int16_t		sadb_sa_natt_port;
-		u_int16_t		sadb_reserved0;
-		u_int32_t		sadb_reserved1;
-	};
-#endif
-
-/** 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;
-
-	/**
-	 * List of exclude routes (exclude_route_t)
-	 */
-	linked_list_t *excludes;
-
-	/**
-	 * Hash table of IPsec SAs using policies (ipsec_sa_t)
-	 */
-	hashtable_t *sas;
-
-	/**
-	 * whether to install routes along policies
-	 */
-	bool install_routes;
-
-	/**
-	 * 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 exclude_route_t exclude_route_t;
-
-/**
- * Exclude route definition
- */
-struct exclude_route_t {
-	/** destination address of exclude */
-	host_t *dst;
-	/** source address for route */
-	host_t *src;
-	/** nexthop exclude has been installed */
-	host_t *gtw;
-	/** references to this route */
-	int refs;
-};
-
-/**
- * clean up a route exclude entry
- */
-static void exclude_route_destroy(exclude_route_t *this)
-{
-	this->dst->destroy(this->dst);
-	this->src->destroy(this->src);
-	this->gtw->destroy(this->gtw);
-	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;
-
-	/** reference to exclude route, if any */
-	exclude_route_t *exclude;
-};
-
-/**
- * destroy an route_entry_t object
- */
-static void route_entry_destroy(route_entry_t *this)
-{
-	free(this->if_name);
-	DESTROY_IF(this->src_ip);
-	DESTROY_IF(this->gateway);
-	chunk_free(&this->dst_net);
-	free(this);
-}
-
-/**
- * compare two route_entry_t objects
- */
-static bool route_entry_equals(route_entry_t *a, route_entry_t *b)
-{
-	return a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
-		   a->src_ip->ip_equals(a->src_ip, b->src_ip) &&
-		   a->gateway && b->gateway &&
-		   a->gateway->ip_equals(a->gateway, b->gateway) &&
-		   chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen;
-}
-
-typedef struct ipsec_sa_t ipsec_sa_t;
-
-/**
- * IPsec SA assigned to a policy.
- */
-struct ipsec_sa_t {
-	/** Source address of this SA */
-	host_t *src;
-
-	/** Destination address of this SA */
-	host_t *dst;
-
-	/** Description of this SA */
-	ipsec_sa_cfg_t cfg;
-
-	/** Reference count for this SA */
-	refcount_t refcount;
-};
-
-/**
- * Hash function for ipsec_sa_t objects
- */
-static u_int ipsec_sa_hash(ipsec_sa_t *sa)
-{
-	return chunk_hash_inc(sa->src->get_address(sa->src),
-						  chunk_hash_inc(sa->dst->get_address(sa->dst),
-						  chunk_hash(chunk_from_thing(sa->cfg))));
-}
-
-/**
- * Equality function for ipsec_sa_t objects
- */
-static bool ipsec_sa_equals(ipsec_sa_t *sa, ipsec_sa_t *other_sa)
-{
-	return sa->src->ip_equals(sa->src, other_sa->src) &&
-		   sa->dst->ip_equals(sa->dst, other_sa->dst) &&
-		   memeq(&sa->cfg, &other_sa->cfg, sizeof(ipsec_sa_cfg_t));
-}
-
-/**
- * Allocate or reference an IPsec SA object
- */
-static ipsec_sa_t *ipsec_sa_create(private_kernel_pfkey_ipsec_t *this,
-								   host_t *src, host_t *dst,
-								   ipsec_sa_cfg_t *cfg)
-{
-	ipsec_sa_t *sa, *found;
-	INIT(sa,
-		.src = src,
-		.dst = dst,
-		.cfg = *cfg,
-	);
-	found = this->sas->get(this->sas, sa);
-	if (!found)
-	{
-		sa->src = src->clone(src);
-		sa->dst = dst->clone(dst);
-		this->sas->put(this->sas, sa, sa);
-	}
-	else
-	{
-		free(sa);
-		sa = found;
-	}
-	ref_get(&sa->refcount);
-	return sa;
-}
-
-/**
- * Release and destroy an IPsec SA object
- */
-static void ipsec_sa_destroy(private_kernel_pfkey_ipsec_t *this,
-							 ipsec_sa_t *sa)
-{
-	if (ref_put(&sa->refcount))
-	{
-		this->sas->remove(this->sas, sa);
-		DESTROY_IF(sa->src);
-		DESTROY_IF(sa->dst);
-		free(sa);
-	}
-}
-
-typedef struct policy_sa_t policy_sa_t;
-typedef struct policy_sa_in_t policy_sa_in_t;
-
-/**
- * Mapping between a policy and an IPsec SA.
- */
-struct policy_sa_t {
-	/** Priority assigned to the policy when installed with this SA */
-	u_int32_t priority;
-
-	/** Type of the policy */
-	policy_type_t type;
-
-	/** Assigned SA */
-	ipsec_sa_t *sa;
-};
-
-/**
- * For input policies we also cache the traffic selectors in order to install
- * the route.
- */
-struct policy_sa_in_t {
-	/** Generic interface */
-	policy_sa_t generic;
-
-	/** Source traffic selector of this policy */
-	traffic_selector_t *src_ts;
-
-	/** Destination traffic selector of this policy */
-	traffic_selector_t *dst_ts;
-};
-
-/**
- * Create a policy_sa(_in)_t object
- */
-static policy_sa_t *policy_sa_create(private_kernel_pfkey_ipsec_t *this,
-	policy_dir_t dir, policy_type_t type, host_t *src, host_t *dst,
-	traffic_selector_t *src_ts, traffic_selector_t *dst_ts, ipsec_sa_cfg_t *cfg)
-{
-	policy_sa_t *policy;
-
-	if (dir == POLICY_IN)
-	{
-		policy_sa_in_t *in;
-		INIT(in,
-			.src_ts = src_ts->clone(src_ts),
-			.dst_ts = dst_ts->clone(dst_ts),
-		);
-		policy = &in->generic;
-	}
-	else
-	{
-		INIT(policy, .priority = 0);
-	}
-	policy->type = type;
-	policy->sa = ipsec_sa_create(this, src, dst, cfg);
-	return policy;
-}
-
-/**
- * Destroy a policy_sa(_in)_t object
- */
-static void policy_sa_destroy(policy_sa_t *policy, policy_dir_t *dir,
-							  private_kernel_pfkey_ipsec_t *this)
-{
-	if (*dir == POLICY_IN)
-	{
-		policy_sa_in_t *in = (policy_sa_in_t*)policy;
-		in->src_ts->destroy(in->src_ts);
-		in->dst_ts->destroy(in->dst_ts);
-	}
-	ipsec_sa_destroy(this, policy->sa);
-	free(policy);
-}
-
-typedef struct policy_entry_t policy_entry_t;
-
-/**
- * installed kernel policy.
- */
-struct policy_entry_t {
-	/** 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;
-
-	/** List of SAs this policy is used by, ordered by priority */
-	linked_list_t *used_by;
-};
-
-/**
- * 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;
-	INIT(policy,
-		.direction = dir,
-	);
-	u_int16_t port;
-	u_int8_t proto;
-
-	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 */
-	proto = max(src_ts->get_protocol(src_ts), dst_ts->get_protocol(dst_ts));
-	/* map the ports to ICMP type/code how the Linux kernel expects them, that
-	 * is, type in src, code in dst */
-	if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6)
-	{
-		port = max(policy->src.net->get_port(policy->src.net),
-				   policy->dst.net->get_port(policy->dst.net));
-		policy->src.net->set_port(policy->src.net,
-								  traffic_selector_icmp_type(port));
-		policy->dst.net->set_port(policy->dst.net,
-								  traffic_selector_icmp_code(port));
-	}
-	else if (!proto)
-	{
-		proto = IPSEC_PROTO_ANY;
-	}
-	policy->src.proto = policy->dst.proto = proto;
-
-	return policy;
-}
-
-/**
- * Destroy a policy_entry_t object
- */
-static void policy_entry_destroy(policy_entry_t *policy,
-								 private_kernel_pfkey_ipsec_t *this)
-{
-	if (policy->route)
-	{
-		route_entry_destroy(policy->route);
-	}
-	if (policy->used_by)
-	{
-		policy->used_by->invoke_function(policy->used_by,
-										(linked_list_invoke_t)policy_sa_destroy,
-										 &policy->direction, this);
-		policy->used_by->destroy(policy->used_by);
-	}
-	DESTROY_IF(policy->src.net);
-	DESTROY_IF(policy->dst.net);
-	free(policy);
-}
-
-/**
- * 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;
-}
-
-/**
- * Calculate the priority of a policy
- */
-static inline u_int32_t get_priority(policy_entry_t *policy,
-									 policy_priority_t prio)
-{
-	u_int32_t priority = PRIO_BASE;
-	switch (prio)
-	{
-		case POLICY_PRIORITY_FALLBACK:
-			priority <<= 1;
-			/* fall-through */
-		case POLICY_PRIORITY_ROUTED:
-			priority <<= 1;
-			/* fall-through */
-		case POLICY_PRIORITY_DEFAULT:
-			priority <<= 1;
-			/* fall-trough */
-		case POLICY_PRIORITY_PASS:
-			break;
-	}
-	/* calculate priority based on selector size, small size = high prio */
-	priority -= policy->src.mask;
-	priority -= policy->dst.mask;
-	priority <<= 2; /* make some room for the two flags */
-	priority += policy->src.net->get_port(policy->src.net) ||
-				policy->dst.net->get_port(policy->dst.net) ?
-				0 : 2;
-	priority += policy->src.proto != IPSEC_PROTO_ANY ? 0 : 1;
-	return priority;
-}
-
-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_EXT_MAX,
-	"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 protocol identifier to the PF_KEY sa type
- */
-static u_int8_t proto2satype(u_int8_t proto)
-{
-	switch (proto)
-	{
-		case IPPROTO_ESP:
-			return SADB_SATYPE_ESP;
-		case IPPROTO_AH:
-			return SADB_SATYPE_AH;
-		case IPPROTO_COMP:
-			return SADB_X_SATYPE_IPCOMP;
-		default:
-			return proto;
-	}
-}
-
-/**
- * convert a PF_KEY sa type to a protocol identifier
- */
-static u_int8_t satype2proto(u_int8_t satype)
-{
-	switch (satype)
-	{
-		case SADB_SATYPE_ESP:
-			return IPPROTO_ESP;
-		case SADB_SATYPE_AH:
-			return IPPROTO_AH;
-		case SADB_X_SATYPE_IPCOMP:
-			return IPPROTO_COMP;
-		default:
-			return satype;
-	}
-}
-
-/**
- * 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;
-#ifdef HAVE_IPSEC_MODE_BEET
-		case MODE_BEET:
-			return IPSEC_MODE_BEET;
-#endif
-		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;
-#ifdef HAVE_IPSEC_DIR_FWD
-		case POLICY_FWD:
-			return IPSEC_DIR_FWD;
-#endif
-		default:
-			return IPSEC_DIR_INVALID;
-	}
-}
-
-/**
- * convert the policy type to the one defined in ipsec.h
- */
-static inline u_int16_t type2kernel(policy_type_t type)
-{
-	switch (type)
-	{
-		case POLICY_IPSEC:
-			return IPSEC_POLICY_IPSEC;
-		case POLICY_PASS:
-			return IPSEC_POLICY_NONE;
-		case POLICY_DROP:
-			return IPSEC_POLICY_DISCARD;
-	}
-	return type;
-}
-
-#ifdef SADB_X_MIGRATE
-/**
- * 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;
-#ifdef HAVE_IPSEC_DIR_FWD
-		case IPSEC_DIR_FWD:
-			return POLICY_FWD;
-#endif
-		default:
-			return dir;
-	}
-}
-#endif /*SADB_X_MIGRATE*/
-
-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			},
-#ifdef SADB_X_EALG_AESCTR
-	{ENCR_AES_CTR,				SADB_X_EALG_AESCTR			},
-#endif
-/*  {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	}, */
-#ifdef SADB_X_EALG_AES_GCM_ICV8 /* assume the others are defined too */
-	{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	},
-#endif
-#ifdef SADB_X_EALG_CAMELLIACBC
-	{ENCR_CAMELLIA_CBC,			SADB_X_EALG_CAMELLIACBC		},
-#endif
-	{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,							}, */
-#ifdef SADB_X_AALG_AES_XCBC_MAC
-	{AUTH_AES_XCBC_96,			SADB_X_AALG_AES_XCBC_MAC,	},
-#endif
-	{END_OF_LIST,				0,							},
-};
-
-/**
- * Algorithms for IPComp, unused yet
- */
-static kernel_algorithm_t compression_algs[] = {
-/*	{IPCOMP_OUI,				0							}, */
-	{IPCOMP_DEFLATE,			SADB_X_CALG_DEFLATE			},
-#ifdef SADB_X_CALG_LZS
-	{IPCOMP_LZS,				SADB_X_CALG_LZS				},
-#endif
-#ifdef SADB_X_CALG_LZJH
-	{IPCOMP_LZJH,				SADB_X_CALG_LZJH			},
-#endif
-	{END_OF_LIST,				0							},
-};
-
-/**
- * Look up a kernel algorithm ID and its key size
- */
-static int lookup_algorithm(transform_type_t type, int ikev2)
-{
-	kernel_algorithm_t *list;
-	u_int16_t alg = 0;
-
-	switch (type)
-	{
-		case ENCRYPTION_ALGORITHM:
-			list = encryption_algs;
-			break;
-		case INTEGRITY_ALGORITHM:
-			list = integrity_algs;
-			break;
-		case COMPRESSION_ALGORITHM:
-			list = compression_algs;
-			break;
-		default:
-			return 0;
-	}
-	while (list->ikev2 != END_OF_LIST)
-	{
-		if (ikev2 == list->ikev2)
-		{
-			return list->kernel;
-		}
-		list++;
-	}
-	hydra->kernel_interface->lookup_algorithm(hydra->kernel_interface, ikev2,
-											  type, &alg, NULL);
-	return alg;
-}
-
-/**
- * Helper to set a port in a sockaddr_t, the port has to be in host order
- */
-static void set_port(sockaddr_t *addr, u_int16_t port)
-{
-	switch (addr->sa_family)
-	{
-		case AF_INET:
-		{
-			struct sockaddr_in *sin = (struct sockaddr_in*)addr;
-			sin->sin_port = htons(port);
-			break;
-		}
-		case AF_INET6:
-		{
-			struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)addr;
-			sin6->sin6_port = htons(port);
-			break;
-		}
-	}
-}
-
-/**
- * Copy a host_t as sockaddr_t to the given memory location.
- * @return		the number of bytes copied
- */
-static size_t hostcpy(void *dest, host_t *host, bool include_port)
-{
-	sockaddr_t *addr = host->get_sockaddr(host), *dest_addr = dest;
-	socklen_t *len = host->get_sockaddr_len(host);
-
-	memcpy(dest, addr, *len);
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
-	dest_addr->sa_len = *len;
-#endif
-	if (!include_port)
-	{
-		set_port(dest_addr, 0);
-	}
-	return *len;
-}
-
-/**
- * add a host to the given sadb_msg
- */
-static void add_addr_ext(struct sadb_msg *msg, host_t *host, u_int16_t type,
-						 u_int8_t proto, u_int8_t prefixlen, bool include_port)
-{
-	struct sadb_address *addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
-	size_t len;
-
-	addr->sadb_address_exttype = type;
-	addr->sadb_address_proto = proto;
-	addr->sadb_address_prefixlen = prefixlen;
-	len = hostcpy(addr + 1, host, include_port);
-	addr->sadb_address_len = PFKEY_LEN(sizeof(*addr) + len);
-	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;
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
-	saddr->sa_len = len;
-#endif
-	addr->sadb_address_len = PFKEY_LEN(sizeof(*addr) + len);
-	PFKEY_EXT_ADD(msg, addr);
-}
-
-#ifdef HAVE_NATT
-/**
- * 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(*nat_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(*nat_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(*nat_port));
-	nat_port->sadb_x_nat_t_port_port = htons(dst->get_port(dst));
-	PFKEY_EXT_ADD(msg, nat_port);
-}
-#endif /*HAVE_NATT*/
-
-/**
- * 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;
-	u_int8_t proto;
-
-	proto = address->sadb_address_proto;
-	proto = proto == IPSEC_PROTO_ANY ? 0 : proto;
-
-	/* 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,
-											 proto, host->get_port(host),
-											 host->get_port(host) ?: 65535);
-	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)))
-	{
-		DBG3(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);
-
-	/* FIXME: our usage of sequence numbers is probably wrong. check RFC 2367,
-	 * in particular the behavior in response to an SADB_ACQUIRE. */
-	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)
-		{
-			DBG2(DBG_KNL, "received PF_KEY message with unexpected sequence "
-						  "number, was %d expected %d", msg->sadb_msg_seq,
-						  this->seq);
-			if (msg->sadb_msg_seq == 0)
-			{
-				/* FreeBSD and Mac OS X do this for the response to
-				 * SADB_X_SPDGET (but not for the response to SADB_GET).
-				 * FreeBSD: 'key_spdget' in /usr/src/sys/netipsec/key.c. */
-			}
-			else if (msg->sadb_msg_seq < this->seq)
-			{
-				continue;
-			}
-			else
-			{
-				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;
-	policy_sa_t *sa;
-
-	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 &&
-		policy->used_by->get_first(policy->used_by, (void**)&sa) == SUCCESS)
-	{
-		reqid = sa->sa->cfg.reqid;
-	}
-	else
-	{
-		DBG1(DBG_KNL, "received an SADB_ACQUIRE with policy id %d but no "
-					  "matching policy found", index);
-	}
-	this->mutex->unlock(this->mutex);
-
-	src_ts = sadb_address2ts(response.src);
-	dst_ts = sadb_address2ts(response.dst);
-
-	hydra->kernel_interface->acquire(hydra->kernel_interface, reqid, src_ts,
-									 dst_ts);
-}
-
-/**
- * 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;
-	u_int8_t protocol;
-	u_int32_t spi;
-	host_t *dst;
-	bool hard;
-
-	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 = satype2proto(msg->sadb_msg_satype);
-	spi = response.sa->sadb_sa_spi;
-	hard = response.lft_hard != NULL;
-
-	if (protocol == IPPROTO_ESP || protocol == IPPROTO_AH)
-	{
-		dst = host_create_from_sockaddr((sockaddr_t*)(response.dst + 1));
-		if (dst)
-		{
-			hydra->kernel_interface->expire(hydra->kernel_interface, protocol,
-											spi, dst, hard);
-			dst->destroy(dst);
-		}
-	}
-}
-
-#ifdef SADB_X_MIGRATE
-/**
- * Process a SADB_X_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;
-
-	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)
-	{
-		hydra->kernel_interface->migrate(hydra->kernel_interface, reqid,
-										 src_ts, dst_ts, dir, local, remote);
-	}
-	else
-	{
-		DESTROY_IF(src_ts);
-		DESTROY_IF(dst_ts);
-		DESTROY_IF(local);
-		DESTROY_IF(remote);
-	}
-}
-#endif /*SADB_X_MIGRATE*/
-
-#ifdef SADB_X_NAT_T_NEW_MAPPING
-/**
- * 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;
-	sockaddr_t *sa;
-	host_t *dst, *new;
-
-	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;
-
-	if (satype2proto(msg->sadb_msg_satype) != IPPROTO_ESP)
-	{
-		return;
-	}
-
-	sa = (sockaddr_t*)(response.dst + 1);
-	dst = host_create_from_sockaddr(sa);
-	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);
-			break;
-		}
-		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);
-			break;
-		}
-		default:
-			break;
-	}
-	if (dst)
-	{
-		new = host_create_from_sockaddr(sa);
-		if (new)
-		{
-			hydra->kernel_interface->mapping(hydra->kernel_interface,
-											 IPPROTO_ESP, spi, dst, new);
-			new->destroy(new);
-		}
-		dst->destroy(dst);
-	}
-}
-#endif /*SADB_X_NAT_T_NEW_MAPPING*/
-
-/**
- * Receives events from kernel
- */
-static bool receive_events(private_kernel_pfkey_ipsec_t *this, int fd,
-						   watcher_event_t event)
-{
-	unsigned char buf[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg = (struct sadb_msg*)buf;
-	int len;
-
-	len = recvfrom(this->socket_events, buf, sizeof(buf), MSG_DONTWAIT, NULL, 0);
-	if (len < 0)
-	{
-		switch (errno)
-		{
-			case EINTR:
-				/* interrupted, try again */
-				return TRUE;
-			case EAGAIN:
-				/* no data ready, select again */
-				return TRUE;
-			default:
-				DBG1(DBG_KNL, "unable to receive from PF_KEY event socket");
-				sleep(1);
-				return TRUE;
-		}
-	}
-
-	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 TRUE;
-	}
-	if (msg->sadb_msg_pid != 0)
-	{	/* not from kernel. not interested, try another one */
-		return TRUE;
-	}
-	if (msg->sadb_msg_len > len / PFKEY_ALIGNMENT)
-	{
-		DBG1(DBG_KNL, "buffer was too small to receive the complete "
-					  "PF_KEY message");
-		return TRUE;
-	}
-
-	switch (msg->sadb_msg_type)
-	{
-		case SADB_ACQUIRE:
-			process_acquire(this, msg);
-			break;
-		case SADB_EXPIRE:
-			process_expire(this, msg);
-			break;
-#ifdef SADB_X_MIGRATE
-		case SADB_X_MIGRATE:
-			process_migrate(this, msg);
-			break;
-#endif /*SADB_X_MIGRATE*/
-#ifdef SADB_X_NAT_T_NEW_MAPPING
-		case SADB_X_NAT_T_NEW_MAPPING:
-			process_mapping(this, msg);
-			break;
-#endif /*SADB_X_NAT_T_NEW_MAPPING*/
-		default:
-			break;
-	}
-
-	return TRUE;
-}
-
-/**
- * Get an SPI for a specific protocol from the kernel.
- */
-
-static status_t get_spi_internal(private_kernel_pfkey_ipsec_t *this,
-	host_t *src, host_t *dst, u_int8_t proto, u_int32_t min, u_int32_t max,
-	u_int32_t *spi)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg, *out;
-	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 = proto2satype(proto);
-	msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
-
-	add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
-	add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
-
-	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 = min;
-	range->sadb_spirange_max = max;
-	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;
-}
-
-METHOD(kernel_ipsec_t, get_spi, status_t,
-	private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
-	u_int8_t protocol, u_int32_t *spi)
-{
-	if (get_spi_internal(this, src, dst, protocol,
-						 0xc0000000, 0xcFFFFFFF, spi) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to get SPI");
-		return FAILED;
-	}
-
-	DBG2(DBG_KNL, "got SPI %.8x", ntohl(*spi));
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, get_cpi, status_t,
-	private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
-	u_int16_t *cpi)
-{
-	u_int32_t received_spi = 0;
-
-	DBG2(DBG_KNL, "getting CPI");
-
-	if (get_spi_internal(this, src, dst, IPPROTO_COMP,
-						 0x100, 0xEFFF, &received_spi) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to get CPI");
-		return FAILED;
-	}
-
-	*cpi = htons((u_int16_t)ntohl(received_spi));
-
-	DBG2(DBG_KNL, "got CPI %.4x", ntohs(*cpi));
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, add_sa, status_t,
-	private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi,
-	u_int8_t protocol, u_int32_t reqid, mark_t mark, u_int32_t tfc,
-	lifetime_cfg_t *lifetime, 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, u_int32_t replay_window,
-	bool initiator, bool encap, bool esn, bool inbound, bool update,
-	linked_list_t *src_ts, linked_list_t *dst_ts)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg, *out;
-	struct sadb_sa *sa;
-	struct sadb_x_sa2 *sa2;
-	struct sadb_lifetime *lft;
-	struct sadb_key *key;
-	size_t len;
-
-	/* 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)
-	{
-		lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}};
-		add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark,
-			   tfc, &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED,
-			   chunk_empty, mode, ipcomp, 0, 0, FALSE, FALSE, FALSE, inbound,
-			   update, NULL, NULL);
-		ipcomp = IPCOMP_NONE;
-		/* use transport mode ESP SA, IPComp uses tunnel mode */
-		mode = MODE_TRANSPORT;
-	}
-
-	if (update)
-	{
-		/* As we didn't know the reqid during SPI allocation, we used reqid
-		 * zero. Unfortunately we can't SADB_UPDATE to the new reqid, hence we
-		 * have to delete the SPI allocation state manually. The reqid
-		 * selector does not count for that, therefore we have to delete
-		 * that state before installing the new SA to avoid deleting the
-		 * the new state after installing it. */
-		mark_t zeromark = {0, 0};
-
-		if (this->public.interface.del_sa(&this->public.interface,
-					src, dst, spi, protocol, 0, zeromark) != SUCCESS)
-		{
-			DBG1(DBG_KNL, "deleting SPI allocation SA failed");
-		}
-	}
-
-	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 = SADB_ADD;
-	msg->sadb_msg_satype = proto2satype(protocol);
-	msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
-
-#ifdef __APPLE__
-	if (encap)
-	{
-		struct sadb_sa_2 *sa_2;
-		sa_2 = (struct sadb_sa_2*)PFKEY_EXT_ADD_NEXT(msg);
-		sa_2->sadb_sa_natt_port = dst->get_port(dst);
-		sa = &sa_2->sa;
-		sa->sadb_sa_flags |= SADB_X_EXT_NATT;
-		len = sizeof(struct sadb_sa_2);
-	}
-	else
-#endif
-	{
-		sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
-		len = sizeof(struct sadb_sa);
-	}
-	sa->sadb_sa_exttype = SADB_EXT_SA;
-	sa->sadb_sa_len = PFKEY_LEN(len);
-	sa->sadb_sa_spi = spi;
-	if (protocol == IPPROTO_COMP)
-	{
-		sa->sadb_sa_encrypt = lookup_algorithm(COMPRESSION_ALGORITHM, ipcomp);
-	}
-	else
-	{
-		/* Linux interprets sadb_sa_replay as number of packets/bits in the
-		 * replay window, whereas on BSD it's the size of the window in bytes */
-#ifdef __linux__
-		sa->sadb_sa_replay = min(replay_window, 32);
-#else
-		sa->sadb_sa_replay = (replay_window + 7) / 8;
-#endif
-		sa->sadb_sa_auth = lookup_algorithm(INTEGRITY_ALGORITHM, int_alg);
-		sa->sadb_sa_encrypt = lookup_algorithm(ENCRYPTION_ALGORITHM, 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);
-
-	add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
-	add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
-
-	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_allocations = lifetime->packets.rekey;
-	lft->sadb_lifetime_bytes = lifetime->bytes.rekey;
-	lft->sadb_lifetime_addtime = lifetime->time.rekey;
-	lft->sadb_lifetime_usetime = 0; /* we only use addtime */
-	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_allocations = lifetime->packets.life;
-	lft->sadb_lifetime_bytes = lifetime->bytes.life;
-	lft->sadb_lifetime_addtime = lifetime->time.life;
-	lft->sadb_lifetime_usetime = 0; /* we only use addtime */
-	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);
-	}
-
-#ifdef HAVE_NATT
-	if (encap)
-	{
-		add_encap_ext(msg, src, dst);
-	}
-#endif /*HAVE_NATT*/
-
-	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;
-}
-
-METHOD(kernel_ipsec_t, update_sa, status_t,
-	private_kernel_pfkey_ipsec_t *this, u_int32_t spi, u_int8_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, mark_t mark)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg, *out;
-	struct sadb_sa *sa;
-	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;
-	}
-
-	/* 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, mark);
-	}
-
-	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 = proto2satype(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. */
-	add_anyaddr_ext(msg, dst->get_family(dst), SADB_EXT_ADDRESS_SRC);
-	add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
-
-	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 = proto2satype(protocol);
-	msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
-
-#ifdef __APPLE__
-	{
-		struct sadb_sa_2 *sa_2;
-		sa_2 = (struct sadb_sa_2*)PFKEY_EXT_ADD_NEXT(msg);
-		sa_2->sa.sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa_2));
-		memcpy(&sa_2->sa, response.sa, sizeof(struct sadb_sa));
-		if (encap)
-		{
-			sa_2->sadb_sa_natt_port = new_dst->get_port(new_dst);
-			sa_2->sa.sadb_sa_flags |= SADB_X_EXT_NATT;
-		}
-	}
-#else
-	PFKEY_EXT_COPY(msg, response.sa);
-#endif
-	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);
-	}
-
-#ifdef HAVE_NATT
-	if (new_encap)
-	{
-		add_encap_ext(msg, new_src, new_dst);
-	}
-#endif /*HAVE_NATT*/
-
-	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;
-}
-
-METHOD(kernel_ipsec_t, query_sa, status_t,
-	private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
-	u_int32_t spi, u_int8_t protocol, mark_t mark,
-	u_int64_t *bytes, u_int64_t *packets, time_t *time)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg, *out;
-	struct sadb_sa *sa;
-	pfkey_msg_t response;
-	size_t len;
-
-	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 = proto2satype(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 Linux Kernel doesn't care for the src address, but other systems do
-	 * (e.g. FreeBSD)
-	 */
-	add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
-	add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
-
-	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", ntohl(spi));
-		free(out);
-		return FAILED;
-	}
-	if (bytes)
-	{
-		*bytes = response.lft_current->sadb_lifetime_bytes;
-	}
-	if (packets)
-	{
-		/* at least on Linux and FreeBSD this contains the number of packets */
-		*packets = response.lft_current->sadb_lifetime_allocations;
-	}
-	if (time)
-	{
-#ifdef __APPLE__
-		/* OS X uses the "last" time of use in usetime */
-		*time = response.lft_current->sadb_lifetime_usetime;
-#else /* !__APPLE__ */
-		/* on Linux, sadb_lifetime_usetime is set to the "first" time of use,
-		 * which is actually correct according to PF_KEY. We have to query
-		 * policies for the last usetime. */
-		*time = 0;
-#endif /* !__APPLE__ */
-	}
-
-	free(out);
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, del_sa, status_t,
-	private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
-	u_int32_t spi, u_int8_t protocol, u_int16_t cpi, mark_t mark)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg, *out;
-	struct sadb_sa *sa;
-	size_t len;
-
-	/* if IPComp was used, we first delete the additional IPComp SA */
-	if (cpi)
-	{
-		del_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0, mark);
-	}
-
-	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 = proto2satype(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 Linux Kernel doesn't care for the src address, but other systems do
-	 * (e.g. FreeBSD)
-	 */
-	add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE);
-	add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE);
-
-	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;
-}
-
-METHOD(kernel_ipsec_t, flush_sas, status_t,
-	private_kernel_pfkey_ipsec_t *this)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg, *out;
-	struct {
-		u_int8_t proto;
-		char *name;
-	} protos[] = {
-		{ SADB_SATYPE_AH, "AH" },
-		{ SADB_SATYPE_ESP, "ESP" },
-		{ SADB_X_SATYPE_IPCOMP, "IPComp" },
-	};
-	size_t len;
-	int i;
-
-	memset(&request, 0, sizeof(request));
-
-	msg = (struct sadb_msg*)request;
-	msg->sadb_msg_version = PF_KEY_V2;
-	msg->sadb_msg_type = SADB_FLUSH;
-	msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
-
-	for (i = 0; i < countof(protos); i++)
-	{
-		DBG2(DBG_KNL, "flushing all %s SAD entries", protos[i].name);
-
-		msg->sadb_msg_satype = protos[i].proto;
-		if (pfkey_send(this, msg, &out, &len) != SUCCESS)
-		{
-			DBG1(DBG_KNL, "unable to flush %s SAD entries", protos[i].name);
-			return FAILED;
-		}
-		else if (out->sadb_msg_errno)
-		{
-			DBG1(DBG_KNL, "unable to flush %s SAD entries: %s (%d)",
-				 protos[i].name, strerror(out->sadb_msg_errno),
-				 out->sadb_msg_errno);
-			free(out);
-			return FAILED;
-		}
-		free(out);
-	}
-	return SUCCESS;
-}
-
-/**
- * Add an explicit exclude route to a routing entry
- */
-static void add_exclude_route(private_kernel_pfkey_ipsec_t *this,
-							  route_entry_t *route, host_t *src, host_t *dst)
-{
-	enumerator_t *enumerator;
-	exclude_route_t *exclude;
-	host_t *gtw;
-
-	enumerator = this->excludes->create_enumerator(this->excludes);
-	while (enumerator->enumerate(enumerator, &exclude))
-	{
-		if (dst->ip_equals(dst, exclude->dst))
-		{
-			route->exclude = exclude;
-			exclude->refs++;
-		}
-	}
-	enumerator->destroy(enumerator);
-
-	if (!route->exclude)
-	{
-		DBG2(DBG_KNL, "installing new exclude route for %H src %H", dst, src);
-		gtw = hydra->kernel_interface->get_nexthop(hydra->kernel_interface,
-												   dst, -1, NULL);
-		if (gtw)
-		{
-			char *if_name = NULL;
-
-			if (hydra->kernel_interface->get_interface(
-									hydra->kernel_interface, src, &if_name) &&
-				hydra->kernel_interface->add_route(hydra->kernel_interface,
-									dst->get_address(dst),
-									dst->get_family(dst) == AF_INET ? 32 : 128,
-									gtw, src, if_name) == SUCCESS)
-			{
-				INIT(exclude,
-					.dst = dst->clone(dst),
-					.src = src->clone(src),
-					.gtw = gtw->clone(gtw),
-					.refs = 1,
-				);
-				route->exclude = exclude;
-				this->excludes->insert_last(this->excludes, exclude);
-			}
-			else
-			{
-				DBG1(DBG_KNL, "installing exclude route for %H failed", dst);
-			}
-			gtw->destroy(gtw);
-			free(if_name);
-		}
-		else
-		{
-			DBG1(DBG_KNL, "gateway lookup for for %H failed", dst);
-		}
-	}
-}
-
-/**
- * Remove an exclude route attached to a routing entry
- */
-static void remove_exclude_route(private_kernel_pfkey_ipsec_t *this,
-								 route_entry_t *route)
-{
-	if (route->exclude)
-	{
-		enumerator_t *enumerator;
-		exclude_route_t *exclude;
-		bool removed = FALSE;
-		host_t *dst;
-
-		enumerator = this->excludes->create_enumerator(this->excludes);
-		while (enumerator->enumerate(enumerator, &exclude))
-		{
-			if (route->exclude == exclude)
-			{
-				if (--exclude->refs == 0)
-				{
-					this->excludes->remove_at(this->excludes, enumerator);
-					removed = TRUE;
-					break;
-				}
-			}
-		}
-		enumerator->destroy(enumerator);
-
-		if (removed)
-		{
-			char *if_name = NULL;
-
-			dst = route->exclude->dst;
-			DBG2(DBG_KNL, "uninstalling exclude route for %H src %H",
-				 dst, route->exclude->src);
-			if (hydra->kernel_interface->get_interface(
-									hydra->kernel_interface,
-									route->exclude->src, &if_name) &&
-				hydra->kernel_interface->del_route(hydra->kernel_interface,
-									dst->get_address(dst),
-									dst->get_family(dst) == AF_INET ? 32 : 128,
-									route->exclude->gtw, route->exclude->src,
-									if_name) != SUCCESS)
-			{
-				DBG1(DBG_KNL, "uninstalling exclude route for %H failed", dst);
-			}
-			exclude_route_destroy(route->exclude);
-			free(if_name);
-		}
-		route->exclude = NULL;
-	}
-}
-
-/**
- * Try to install a route to the given inbound policy
- */
-static bool install_route(private_kernel_pfkey_ipsec_t *this,
-						  policy_entry_t *policy, policy_sa_in_t *in)
-{
-	route_entry_t *route, *old;
-	host_t *host, *src, *dst;
-	bool is_virtual;
-
-	if (hydra->kernel_interface->get_address_by_ts(hydra->kernel_interface,
-									in->dst_ts, &host, &is_virtual) != SUCCESS)
-	{
-		return FALSE;
-	}
-
-	/* switch src/dst, as we handle an IN policy */
-	src = in->generic.sa->dst;
-	dst = in->generic.sa->src;
-
-	INIT(route,
-		.prefixlen = policy->src.mask,
-		.src_ip = host,
-		.dst_net = chunk_clone(policy->src.net->get_address(policy->src.net)),
-	);
-
-	if (!dst->is_anyaddr(dst))
-	{
-		route->gateway = hydra->kernel_interface->get_nexthop(
-									hydra->kernel_interface, dst, -1, src);
-
-		/* if the IP is virtual, we install the route over the interface it has
-		 * been installed on. Otherwise we use the interface we use for IKE, as
-		 * this is required for example on Linux. */
-		if (is_virtual)
-		{
-			src = route->src_ip;
-		}
-	}
-	else
-	{	/* for shunt policies */
-		route->gateway = hydra->kernel_interface->get_nexthop(
-									hydra->kernel_interface, policy->src.net,
-									policy->src.mask, route->src_ip);
-
-		/* we don't have a source address, use the address we found */
-		src = route->src_ip;
-	}
-
-	/* get interface for route, using source address */
-	if (!hydra->kernel_interface->get_interface(hydra->kernel_interface,
-												src, &route->if_name))
-	{
-		route_entry_destroy(route);
-		return FALSE;
-	}
-
-	if (policy->route)
-	{
-		old = policy->route;
-
-		if (route_entry_equals(old, route))
-		{	/* such a route already exists */
-			route_entry_destroy(route);
-			return TRUE;
-		}
-		/* uninstall previously installed route */
-		if (hydra->kernel_interface->del_route(hydra->kernel_interface,
-									old->dst_net, old->prefixlen, old->gateway,
-									old->src_ip, old->if_name) != SUCCESS)
-		{
-			DBG1(DBG_KNL, "error uninstalling route installed with policy "
-				 "%R === %R %N", in->src_ts, in->dst_ts,
-				policy_dir_names, policy->direction);
-		}
-		route_entry_destroy(old);
-		policy->route = NULL;
-	}
-
-	/* if remote traffic selector covers the IKE peer, add an exclude route */
-	if (hydra->kernel_interface->get_features(
-					hydra->kernel_interface) & KERNEL_REQUIRE_EXCLUDE_ROUTE)
-	{
-		if (in->src_ts->is_host(in->src_ts, dst))
-		{
-			DBG1(DBG_KNL, "can't install route for %R === %R %N, conflicts "
-				 "with IKE traffic", in->src_ts, in->dst_ts, policy_dir_names,
-				 policy->direction);
-			route_entry_destroy(route);
-			return FALSE;
-		}
-		if (in->src_ts->includes(in->src_ts, dst))
-		{
-			add_exclude_route(this, route, in->generic.sa->dst, dst);
-		}
-	}
-
-	DBG2(DBG_KNL, "installing route: %R via %H src %H dev %s",
-		 in->src_ts, route->gateway, route->src_ip, route->if_name);
-
-	switch (hydra->kernel_interface->add_route(hydra->kernel_interface,
-							route->dst_net, route->prefixlen, route->gateway,
-							route->src_ip, route->if_name))
-	{
-		case ALREADY_DONE:
-			/* route exists, do not uninstall */
-			remove_exclude_route(this, route);
-			route_entry_destroy(route);
-			return TRUE;
-		case SUCCESS:
-			/* cache the installed route */
-			policy->route = route;
-			return TRUE;
-		default:
-			DBG1(DBG_KNL, "installing route failed: %R via %H src %H dev %s",
-				 in->src_ts, route->gateway, route->src_ip, route->if_name);
-			remove_exclude_route(this, route);
-			route_entry_destroy(route);
-			return FALSE;
-	}
-}
-
-/**
- * Add or update a policy in the kernel.
- *
- * Note: The mutex has to be locked when entering this function.
- */
-static status_t add_policy_internal(private_kernel_pfkey_ipsec_t *this,
-	policy_entry_t *policy, policy_sa_t *mapping, bool update)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg, *out;
-	struct sadb_x_policy *pol;
-	struct sadb_x_ipsecrequest *req;
-	ipsec_sa_t *ipsec = mapping->sa;
-	pfkey_msg_t response;
-	size_t len;
-	ipsec_mode_t proto_mode;
-	status_t status;
-
-	memset(&request, 0, sizeof(request));
-
-	msg = (struct sadb_msg*)request;
-	msg->sadb_msg_version = PF_KEY_V2;
-	msg->sadb_msg_type = update ? 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(policy->direction);
-	pol->sadb_x_policy_type = type2kernel(mapping->type);
-#ifdef HAVE_STRUCT_SADB_X_POLICY_SADB_X_POLICY_PRIORITY
-	pol->sadb_x_policy_priority = mapping->priority;
-#endif
-
-	/* one or more sadb_x_ipsecrequest extensions are added to the
-	 * sadb_x_policy extension */
-	proto_mode = ipsec->cfg.mode;
-
-	req = (struct sadb_x_ipsecrequest*)(pol + 1);
-
-	if (ipsec->cfg.ipcomp.transform != IPCOMP_NONE)
-	{
-		req->sadb_x_ipsecrequest_proto = IPPROTO_COMP;
-
-		/* !!! the length here 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(ipsec->cfg.mode);
-		req->sadb_x_ipsecrequest_reqid = ipsec->cfg.reqid;
-		req->sadb_x_ipsecrequest_level = (policy->direction == POLICY_OUT) ?
-										  IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_USE;
-		if (ipsec->cfg.mode == MODE_TUNNEL)
-		{
-			len = hostcpy(req + 1, ipsec->src, FALSE);
-			req->sadb_x_ipsecrequest_len += len;
-			len = hostcpy((char*)(req + 1) + len, ipsec->dst, FALSE);
-			req->sadb_x_ipsecrequest_len += len;
-			/* use transport mode for other SAs */
-			proto_mode = MODE_TRANSPORT;
-		}
-
-		pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len);
-		req = (struct sadb_x_ipsecrequest*)((char*)(req) +
-											req->sadb_x_ipsecrequest_len);
-	}
-
-	req->sadb_x_ipsecrequest_proto = ipsec->cfg.esp.use ? IPPROTO_ESP
-														: IPPROTO_AH;
-	/* !!! the length here 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(proto_mode);
-	req->sadb_x_ipsecrequest_reqid = ipsec->cfg.reqid;
-	req->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
-	if (proto_mode == MODE_TUNNEL)
-	{
-		len = hostcpy(req + 1, ipsec->src, FALSE);
-		req->sadb_x_ipsecrequest_len += len;
-		len = hostcpy((char*)(req + 1) + len, ipsec->dst, FALSE);
-		req->sadb_x_ipsecrequest_len += len;
-	}
-
-	pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len);
-	PFKEY_EXT_ADD(msg, pol);
-
-	add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto,
-				 policy->src.mask, TRUE);
-	add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto,
-				 policy->dst.mask, TRUE);
-
-#ifdef __FreeBSD__
-	{	/* on FreeBSD a lifetime has to be defined to be able to later query
-		 * the current use time. */
-		struct sadb_lifetime *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 = LONG_MAX;
-		PFKEY_EXT_ADD(msg, lft);
-	}
-#endif
-
-	this->mutex->unlock(this->mutex);
-
-	status = pfkey_send(this, msg, &out, &len);
-	if (status == SUCCESS && !update && out->sadb_msg_errno == EEXIST)
-	{
-		DBG1(DBG_KNL, "policy already exists, try to update it");
-		free(out);
-		msg->sadb_msg_type = SADB_X_SPDUPDATE;
-		status = pfkey_send(this, msg, &out, &len);
-	}
-	if (status != SUCCESS)
-	{
-		return FAILED;
-	}
-	else if (out->sadb_msg_errno)
-	{
-		DBG1(DBG_KNL, "unable to %s policy: %s (%d)",
-					   update ? "update" : "add", 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 %s policy: parsing response from kernel "
-					  "failed", update ? "update" : "add");
-		free(out);
-		return FAILED;
-	}
-
-	/* we try to find the policy again and update the kernel index */
-	this->mutex->lock(this->mutex);
-	if (this->policies->find_first(this->policies, NULL,
-								  (void**)&policy) != SUCCESS)
-	{
-		DBG2(DBG_KNL, "unable to update index, the policy is already gone, "
-					  "ignoring");
-		this->mutex->unlock(this->mutex);
-		free(out);
-		return SUCCESS;
-	}
-	policy->index = response.x_policy->sadb_x_policy_id;
-	free(out);
-
-	/* install a route, if:
-	 * - this is an inbound policy (to just get one for each child)
-	 * - we are in tunnel mode or install a bypass policy
-	 * - routing is not disabled via strongswan.conf
-	 */
-	if (policy->direction == POLICY_IN && this->install_routes &&
-		(mapping->type != POLICY_IPSEC || ipsec->cfg.mode != MODE_TRANSPORT))
-	{
-		install_route(this, policy, (policy_sa_in_t*)mapping);
-	}
-	this->mutex->unlock(this->mutex);
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, add_policy, status_t,
-	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, policy_type_t type, ipsec_sa_cfg_t *sa,
-	mark_t mark, policy_priority_t priority)
-{
-	policy_entry_t *policy, *found = NULL;
-	policy_sa_t *assigned_sa, *current_sa;
-	enumerator_t *enumerator;
-	bool update = TRUE;
-
-	if (dir2kernel(direction) == IPSEC_DIR_INVALID)
-	{	/* FWD policies are not supported on all platforms */
-		return SUCCESS;
-	}
-
-	/* 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, this);
-		policy = found;
-	}
-	else
-	{	/* use the new one, if we have no such policy */
-		this->policies->insert_first(this->policies, policy);
-		policy->used_by = linked_list_create();
-	}
-
-	/* cache the assigned IPsec SA */
-	assigned_sa = policy_sa_create(this, direction, type, src, dst, src_ts,
-								   dst_ts, sa);
-	assigned_sa->priority = get_priority(policy, priority);
-
-	/* insert the SA according to its priority */
-	enumerator = policy->used_by->create_enumerator(policy->used_by);
-	while (enumerator->enumerate(enumerator, (void**)&current_sa))
-	{
-		if (current_sa->priority >= assigned_sa->priority)
-		{
-			break;
-		}
-		update = FALSE;
-	}
-	policy->used_by->insert_before(policy->used_by, enumerator, assigned_sa);
-	enumerator->destroy(enumerator);
-
-	if (!update)
-	{	/* we don't update the policy if the priority is lower than that of the
-		 * currently installed one */
-		this->mutex->unlock(this->mutex);
-		return SUCCESS;
-	}
-
-	DBG2(DBG_KNL, "%s policy %R === %R %N",
-				   found ? "updating" : "adding", src_ts, dst_ts,
-				   policy_dir_names, direction);
-
-	if (add_policy_internal(this, policy, assigned_sa, found) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to %s policy %R === %R %N",
-					   found ? "update" : "add", src_ts, dst_ts,
-					   policy_dir_names, direction);
-		return FAILED;
-	}
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, query_policy, status_t,
-	private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts,
-	traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
-	time_t *use_time)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg, *out;
-	struct sadb_x_policy *pol;
-	policy_entry_t *policy, *found = NULL;
-	pfkey_msg_t response;
-	size_t len;
-
-	if (dir2kernel(direction) == IPSEC_DIR_INVALID)
-	{	/* FWD policies are not supported on all platforms */
-		return NOT_FOUND;
-	}
-
-	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)
-	{
-		DBG1(DBG_KNL, "querying policy %R === %R %N failed, not found", src_ts,
-					   dst_ts, policy_dir_names, direction);
-		policy_entry_destroy(policy, this);
-		this->mutex->unlock(this->mutex);
-		return NOT_FOUND;
-	}
-	policy_entry_destroy(policy, this);
-	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);
-
-	add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto,
-				 policy->src.mask, TRUE);
-	add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto,
-				 policy->dst.mask, TRUE);
-
-	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;
-	}
-	else if (response.lft_current == NULL)
-	{
-		DBG2(DBG_KNL, "unable to query policy %R === %R %N: kernel reports no "
-					  "use time", src_ts, dst_ts, policy_dir_names, direction);
-		free(out);
-		return FAILED;
-	}
-
-	/* we need the monotonic time, but the kernel returns system time. */
-	if (response.lft_current->sadb_lifetime_usetime)
-	{
-		*use_time = time_monotonic(NULL) -
-					(time(NULL) - response.lft_current->sadb_lifetime_usetime);
-	}
-	else
-	{
-		*use_time = 0;
-	}
-	free(out);
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, del_policy, status_t,
-	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, policy_type_t type, ipsec_sa_cfg_t *sa,
-	mark_t mark, policy_priority_t prio)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg, *out;
-	struct sadb_x_policy *pol;
-	policy_entry_t *policy, *found = NULL;
-	policy_sa_t *mapping, *to_remove = NULL;
-	enumerator_t *enumerator;
-	bool first = TRUE, is_installed = TRUE;
-	u_int32_t priority;
-	size_t len;
-	ipsec_sa_t assigned_sa = {
-		.src = src,
-		.dst = dst,
-		.cfg = *sa,
-	};
-
-	if (dir2kernel(direction) == IPSEC_DIR_INVALID)
-	{	/* FWD policies are not supported on all platforms */
-		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)
-	{
-		DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts,
-					   dst_ts, policy_dir_names, direction);
-		policy_entry_destroy(policy, this);
-		this->mutex->unlock(this->mutex);
-		return NOT_FOUND;
-	}
-	policy_entry_destroy(policy, this);
-	policy = found;
-
-	/* remove mapping to SA by reqid and priority, if multiple match, which
-	 * could happen when rekeying due to an address change, remove the oldest */
-	priority = get_priority(policy, prio);
-	enumerator = policy->used_by->create_enumerator(policy->used_by);
-	while (enumerator->enumerate(enumerator, (void**)&mapping))
-	{
-		if (priority == mapping->priority &&
-			ipsec_sa_equals(mapping->sa, &assigned_sa))
-		{
-			to_remove = mapping;
-			is_installed = first;
-		}
-		else if (priority < mapping->priority)
-		{
-			break;
-		}
-		first = FALSE;
-	}
-	enumerator->destroy(enumerator);
-	if (!to_remove)
-	{	/* sanity check */
-		this->mutex->unlock(this->mutex);
-		return SUCCESS;
-	}
-	policy->used_by->remove(policy->used_by, to_remove, NULL);
-	mapping = to_remove;
-
-	if (policy->used_by->get_count(policy->used_by) > 0)
-	{	/* policy is used by more SAs, keep in kernel */
-		DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
-		policy_sa_destroy(mapping, &direction, this);
-
-		if (!is_installed)
-		{	/* no need to update as the policy was not installed for this SA */
-			this->mutex->unlock(this->mutex);
-			return SUCCESS;
-		}
-
-		DBG2(DBG_KNL, "updating policy %R === %R %N", src_ts, dst_ts,
-					   policy_dir_names, direction);
-		policy->used_by->get_first(policy->used_by, (void**)&mapping);
-		if (add_policy_internal(this, policy, mapping, TRUE) != SUCCESS)
-		{
-			DBG1(DBG_KNL, "unable to update policy %R === %R %N",
-						   src_ts, dst_ts, policy_dir_names, direction);
-			return FAILED;
-		}
-		return SUCCESS;
-	}
-
-	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 = type2kernel(mapping->type);
-	PFKEY_EXT_ADD(msg, pol);
-
-	add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto,
-				 policy->src.mask, TRUE);
-	add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto,
-				 policy->dst.mask, TRUE);
-
-	if (policy->route)
-	{
-		route_entry_t *route = policy->route;
-		if (hydra->kernel_interface->del_route(hydra->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);
-		}
-		remove_exclude_route(this, route);
-	}
-
-	this->policies->remove(this->policies, found, NULL);
-	policy_sa_destroy(mapping, &direction, this);
-	policy_entry_destroy(policy, this);
-	this->mutex->unlock(this->mutex);
-
-	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);
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, flush_policies, status_t,
-	private_kernel_pfkey_ipsec_t *this)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg, *out;
-	size_t len;
-
-	memset(&request, 0, sizeof(request));
-
-	DBG2(DBG_KNL, "flushing all policies from SPD");
-
-	msg = (struct sadb_msg*)request;
-	msg->sadb_msg_version = PF_KEY_V2;
-	msg->sadb_msg_type = SADB_X_SPDFLUSH;
-	msg->sadb_msg_satype = SADB_SATYPE_UNSPEC;
-	msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
-
-	if (pfkey_send(this, msg, &out, &len) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to flush SPD entries");
-		return FAILED;
-	}
-	else if (out->sadb_msg_errno)
-	{
-		DBG1(DBG_KNL, "unable to flush SPD entries: %s (%d)",
-					   strerror(out->sadb_msg_errno), out->sadb_msg_errno);
-		free(out);
-		return FAILED;
-	}
-	free(out);
-	return SUCCESS;
-}
-
-/**
- * Register a socket for ACQUIRE/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;
-}
-
-METHOD(kernel_ipsec_t, bypass_socket, bool,
-	private_kernel_pfkey_ipsec_t *this, int fd, int family)
-{
-	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:
-			return FALSE;
-	}
-
-	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));
-		return FALSE;
-	}
-	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));
-		return FALSE;
-	}
-	return TRUE;
-}
-
-METHOD(kernel_ipsec_t, enable_udp_decap, bool,
-	private_kernel_pfkey_ipsec_t *this, int fd, int family, u_int16_t port)
-{
-#ifndef __APPLE__
-	int type = UDP_ENCAP_ESPINUDP;
-
-	if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
-	{
-		DBG1(DBG_KNL, "unable to set UDP_ENCAP: %s", strerror(errno));
-		return FALSE;
-	}
-#else /* __APPLE__ */
-	int intport = port;
-
-	if (sysctlbyname("net.inet.ipsec.esp_port", NULL, NULL, &intport,
-					 sizeof(intport)) != 0)
-	{
-		DBG1(DBG_KNL, "could not set net.inet.ipsec.esp_port to %d: %s",
-			 port, strerror(errno));
-		return FALSE;
-	}
-#endif /* __APPLE__ */
-
-	return TRUE;
-}
-
-METHOD(kernel_ipsec_t, destroy, void,
-	private_kernel_pfkey_ipsec_t *this)
-{
-	if (this->socket > 0)
-	{
-		close(this->socket);
-	}
-	if (this->socket_events > 0)
-	{
-		lib->watcher->remove(lib->watcher, this->socket_events);
-		close(this->socket_events);
-	}
-	this->policies->invoke_function(this->policies,
-								   (linked_list_invoke_t)policy_entry_destroy,
-									this);
-	this->policies->destroy(this->policies);
-	this->excludes->destroy(this->excludes);
-	this->sas->destroy(this->sas);
-	this->mutex->destroy(this->mutex);
-	this->mutex_pfkey->destroy(this->mutex_pfkey);
-	free(this);
-}
-
-/*
- * Described in header.
- */
-kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create()
-{
-	private_kernel_pfkey_ipsec_t *this;
-	bool register_for_events = TRUE;
-	int rcv_buffer;
-
-	INIT(this,
-		.public = {
-			.interface = {
-				.get_spi = _get_spi,
-				.get_cpi = _get_cpi,
-				.add_sa  = _add_sa,
-				.update_sa = _update_sa,
-				.query_sa = _query_sa,
-				.del_sa = _del_sa,
-				.flush_sas = _flush_sas,
-				.add_policy = _add_policy,
-				.query_policy = _query_policy,
-				.del_policy = _del_policy,
-				.flush_policies = _flush_policies,
-				.bypass_socket = _bypass_socket,
-				.enable_udp_decap = _enable_udp_decap,
-				.destroy = _destroy,
-			},
-		},
-		.policies = linked_list_create(),
-		.excludes = linked_list_create(),
-		.sas = hashtable_create((hashtable_hash_t)ipsec_sa_hash,
-								(hashtable_equals_t)ipsec_sa_equals, 32),
-		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
-		.mutex_pfkey = mutex_create(MUTEX_TYPE_DEFAULT),
-		.install_routes = lib->settings->get_bool(lib->settings,
-												  "%s.install_routes", TRUE,
-												  lib->ns),
-	);
-
-	if (streq(lib->ns, "starter"))
-	{	/* starter has no threads, so we do not register for kernel events */
-		register_for_events = FALSE;
-	}
-
-	/* create a PF_KEY socket to communicate with the kernel */
-	this->socket = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
-	if (this->socket <= 0)
-	{
-		DBG1(DBG_KNL, "unable to create PF_KEY socket");
-		destroy(this);
-		return NULL;
-	}
-
-	if (register_for_events)
-	{
-		/* create a PF_KEY socket for ACQUIRE & EXPIRE */
-		this->socket_events = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
-		if (this->socket_events <= 0)
-		{
-			DBG1(DBG_KNL, "unable to create PF_KEY event socket");
-			destroy(this);
-			return NULL;
-		}
-
-		rcv_buffer = lib->settings->get_int(lib->settings,
-					"%s.plugins.kernel-pfkey.events_buffer_size", 0, lib->ns);
-		if (rcv_buffer > 0)
-		{
-			if (setsockopt(this->socket_events, SOL_SOCKET, SO_RCVBUF,
-						   &rcv_buffer, sizeof(rcv_buffer)) == -1)
-			{
-				DBG1(DBG_KNL, "unable to set receive buffer size on PF_KEY "
-					 "event socket: %s", strerror(errno));
-			}
-		}
-
-		/* register the event socket */
-		if (register_pfkey_socket(this, SADB_SATYPE_ESP) != SUCCESS ||
-			register_pfkey_socket(this, SADB_SATYPE_AH) != SUCCESS)
-		{
-			DBG1(DBG_KNL, "unable to register PF_KEY event socket");
-			destroy(this);
-			return NULL;
-		}
-
-		lib->watcher->add(lib->watcher, this->socket_events, WATCHER_READ,
-						  (watcher_cb_t)receive_events, this);
-	}
-
-	return &this->public;
-}
diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_plugin.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_plugin.c
deleted file mode 100644
index 61d5765..0000000
--- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_plugin.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.
- */
-
-
-#include "kernel_pfkey_plugin.h"
-
-#include "kernel_pfkey_ipsec.h"
-
-#include <hydra.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;
-};
-
-METHOD(plugin_t, get_name, char*,
-	private_kernel_pfkey_plugin_t *this)
-{
-	return "kernel-pfkey";
-}
-
-METHOD(plugin_t, get_features, int,
-	private_kernel_pfkey_plugin_t *this, plugin_feature_t *features[])
-{
-	static plugin_feature_t f[] = {
-		PLUGIN_CALLBACK(kernel_ipsec_register, kernel_pfkey_ipsec_create),
-			PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"),
-	};
-	*features = f;
-	return countof(f);
-}
-
-METHOD(plugin_t, destroy, void,
-	private_kernel_pfkey_plugin_t *this)
-{
-	free(this);
-}
-
-/*
- * see header file
- */
-plugin_t *kernel_pfkey_plugin_create()
-{
-	private_kernel_pfkey_plugin_t *this;
-
-	if (!lib->caps->check(lib->caps, CAP_NET_ADMIN))
-	{	/* required to open PF_KEY sockets */
-		DBG1(DBG_KNL, "kernel-pfkey plugin requires CAP_NET_ADMIN capability");
-		return NULL;
-	}
-
-	INIT(this,
-		.public = {
-			.plugin = {
-				.get_name = _get_name,
-				.get_features = _get_features,
-				.destroy = _destroy,
-			},
-		},
-	);
-
-	return &this->public.plugin;
-}
diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_plugin.h b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_plugin.h
deleted file mode 100644
index 51db4d8..0000000
--- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_plugin.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @defgroup kernel_pfkey kernel_pfkey
- * @ingroup hplugins
- *
- * @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;
-};
-
-#endif /** KERNEL_PFKEY_PLUGIN_H_ @}*/
diff --git a/src/libhydra/plugins/kernel_pfroute/Makefile.am b/src/libhydra/plugins/kernel_pfroute/Makefile.am
deleted file mode 100644
index 5129c02..0000000
--- a/src/libhydra/plugins/kernel_pfroute/Makefile.am
+++ /dev/null
@@ -1,19 +0,0 @@
-AM_CPPFLAGS = \
-	-I${linux_headers} \
-	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra
-
-AM_CFLAGS = \
-	$(PLUGIN_CFLAGS)
-
-if MONOLITHIC
-noinst_LTLIBRARIES = libstrongswan-kernel-pfroute.la
-else
-plugin_LTLIBRARIES = libstrongswan-kernel-pfroute.la
-endif
-
-libstrongswan_kernel_pfroute_la_SOURCES = \
-	kernel_pfroute_plugin.h kernel_pfroute_plugin.c \
-	kernel_pfroute_net.h kernel_pfroute_net.c
-
-libstrongswan_kernel_pfroute_la_LDFLAGS = -module -avoid-version
diff --git a/src/libhydra/plugins/kernel_pfroute/Makefile.in b/src/libhydra/plugins/kernel_pfroute/Makefile.in
deleted file mode 100644
index 9f676d2..0000000
--- a/src/libhydra/plugins/kernel_pfroute/Makefile.in
+++ /dev/null
@@ -1,780 +0,0 @@
-# Makefile.in generated by automake 1.14.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 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.
-
- at SET_MAKE@
-
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
-  case $${target_option-} in \
-      ?) ;; \
-      *) echo "am__make_running_with_option: internal error: invalid" \
-              "target option '$${target_option-}' specified" >&2; \
-         exit 1;; \
-  esac; \
-  has_opt=no; \
-  sane_makeflags=$$MAKEFLAGS; \
-  if $(am__is_gnu_make); then \
-    sane_makeflags=$$MFLAGS; \
-  else \
-    case $$MAKEFLAGS in \
-      *\\[\ \	]*) \
-        bs=\\; \
-        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
-          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
-    esac; \
-  fi; \
-  skip_next=no; \
-  strip_trailopt () \
-  { \
-    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
-  }; \
-  for flg in $$sane_makeflags; do \
-    test $$skip_next = yes && { skip_next=no; continue; }; \
-    case $$flg in \
-      *=*|--*) continue;; \
-        -*I) strip_trailopt 'I'; skip_next=yes;; \
-      -*I?*) strip_trailopt 'I';; \
-        -*O) strip_trailopt 'O'; skip_next=yes;; \
-      -*O?*) strip_trailopt 'O';; \
-        -*l) strip_trailopt 'l'; skip_next=yes;; \
-      -*l?*) strip_trailopt 'l';; \
-      -[dEDm]) skip_next=yes;; \
-      -[JT]) skip_next=yes;; \
-    esac; \
-    case $$flg in \
-      *$$target_option*) has_opt=yes; break;; \
-    esac; \
-  done; \
-  test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@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/libhydra/plugins/kernel_pfroute
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
-	$(top_srcdir)/depcomp
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
-	$(top_srcdir)/m4/config/ltoptions.m4 \
-	$(top_srcdir)/m4/config/ltsugar.m4 \
-	$(top_srcdir)/m4/config/ltversion.m4 \
-	$(top_srcdir)/m4/config/lt~obsolete.m4 \
-	$(top_srcdir)/m4/macros/split-package-version.m4 \
-	$(top_srcdir)/m4/macros/with.m4 \
-	$(top_srcdir)/m4/macros/enable-disable.m4 \
-	$(top_srcdir)/m4/macros/add-plugin.m4 \
-	$(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-	$(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_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 = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
-  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
-  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
-  for p in $$list; do echo "$$p $$p"; done | \
-  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
-  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
-    if (++n[$$2] == $(am__install_max)) \
-      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
-    END { for (dir in files) print dir, files[dir] }'
-am__base_list = \
-  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
-  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__uninstall_files_from_dir = { \
-  test -z "$$files" \
-    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
-    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
-         $(am__cd) "$$dir" && rm -f $$files; }; \
-  }
-am__installdirs = "$(DESTDIR)$(plugindir)"
-LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
-libstrongswan_kernel_pfroute_la_LIBADD =
-am_libstrongswan_kernel_pfroute_la_OBJECTS = kernel_pfroute_plugin.lo \
-	kernel_pfroute_net.lo
-libstrongswan_kernel_pfroute_la_OBJECTS =  \
-	$(am_libstrongswan_kernel_pfroute_la_OBJECTS)
-AM_V_lt = $(am__v_lt_ at AM_V@)
-am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 = 
-libstrongswan_kernel_pfroute_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
-	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
-	$(AM_CFLAGS) $(CFLAGS) \
-	$(libstrongswan_kernel_pfroute_la_LDFLAGS) $(LDFLAGS) -o $@
- at MONOLITHIC_FALSE@am_libstrongswan_kernel_pfroute_la_rpath = -rpath \
- at MONOLITHIC_FALSE@	$(plugindir)
- at MONOLITHIC_TRUE@am_libstrongswan_kernel_pfroute_la_rpath =
-AM_V_P = $(am__v_P_ at AM_V@)
-am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_ at AM_V@)
-am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 = 
-AM_V_at = $(am__v_at_ at AM_V@)
-am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 = 
-DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-	$(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_ at AM_V@)
-am__v_CC_ = $(am__v_CC_ at AM_DEFAULT_V@)
-am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 = 
-CCLD = $(CC)
-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-	$(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_ at AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_ at AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo "  CCLD    " $@;
-am__v_CCLD_1 = 
-SOURCES = $(libstrongswan_kernel_pfroute_la_SOURCES)
-DIST_SOURCES = $(libstrongswan_kernel_pfroute_la_SOURCES)
-am__can_run_installinfo = \
-  case $$AM_UPDATE_INFO_DIR in \
-    n|no|NO) false;; \
-    *) (install-info --version) >/dev/null 2>&1;; \
-  esac
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates.  Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
-  BEGIN { nonempty = 0; } \
-  { items[$$0] = 1; nonempty = 1; } \
-  END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique.  This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
-  list='$(am__tagged_files)'; \
-  unique=`for i in $$list; do \
-    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-  done | $(am__uniquify_input)`
-ETAGS = etags
-CTAGS = ctags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-ALLOCA = @ALLOCA@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BFDLIB = @BFDLIB@
-BTLIB = @BTLIB@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
-COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLIB = @DLLIB@
-DLLTOOL = @DLLTOOL@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-EASY_INSTALL = @EASY_INSTALL@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FGREP = @FGREP@
-GEM = @GEM@
-GENHTML = @GENHTML@
-GPERF = @GPERF@
-GPRBUILD = @GPRBUILD@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LCOV = @LCOV@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LEX = @LEX@
-LEXLIB = @LEXLIB@
-LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-MYSQLCFLAG = @MYSQLCFLAG@
-MYSQLCONFIG = @MYSQLCONFIG@
-MYSQLLIB = @MYSQLLIB@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OPENSSL_LIB = @OPENSSL_LIB@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
-PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
-PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
-PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PERL = @PERL@
-PKG_CONFIG = @PKG_CONFIG@
-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
-PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
-PTHREADLIB = @PTHREADLIB@
-PYTHON = @PYTHON@
-PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
-PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
-PYTHON_PLATFORM = @PYTHON_PLATFORM@
-PYTHON_PREFIX = @PYTHON_PREFIX@
-PYTHON_VERSION = @PYTHON_VERSION@
-PY_TEST = @PY_TEST@
-RANLIB = @RANLIB@
-RTLIB = @RTLIB@
-RUBY = @RUBY@
-RUBYGEMDIR = @RUBYGEMDIR@
-RUBYINCLUDE = @RUBYINCLUDE@
-RUBYLIB = @RUBYLIB@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-SOCKLIB = @SOCKLIB@
-STRIP = @STRIP@
-UNWINDLIB = @UNWINDLIB@
-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_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-aikgen_plugins = @aikgen_plugins@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-attest_plugins = @attest_plugins@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-c_plugins = @c_plugins@
-charon_natt_port = @charon_natt_port@
-charon_plugins = @charon_plugins@
-charon_udp_port = @charon_udp_port@
-clearsilver_LIBS = @clearsilver_LIBS@
-cmd_plugins = @cmd_plugins@
-datadir = @datadir@
-datarootdir = @datarootdir@
-dbusservicedir = @dbusservicedir@
-dev_headers = @dev_headers@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-fips_mode = @fips_mode@
-gtk_CFLAGS = @gtk_CFLAGS@
-gtk_LIBS = @gtk_LIBS@
-h_plugins = @h_plugins@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-imcvdir = @imcvdir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-ipsec_script = @ipsec_script@
-ipsec_script_upper = @ipsec_script_upper@
-ipsecdir = @ipsecdir@
-ipsecgroup = @ipsecgroup@
-ipseclibdir = @ipseclibdir@
-ipsecuser = @ipsecuser@
-json_CFLAGS = @json_CFLAGS@
-json_LIBS = @json_LIBS@
-libdir = @libdir@
-libexecdir = @libexecdir@
-libiptc_CFLAGS = @libiptc_CFLAGS@
-libiptc_LIBS = @libiptc_LIBS@
-linux_headers = @linux_headers@
-localedir = @localedir@
-localstatedir = @localstatedir@
-maemo_CFLAGS = @maemo_CFLAGS@
-maemo_LIBS = @maemo_LIBS@
-manager_plugins = @manager_plugins@
-mandir = @mandir@
-medsrv_plugins = @medsrv_plugins@
-mkdir_p = @mkdir_p@
-nm_CFLAGS = @nm_CFLAGS@
-nm_LIBS = @nm_LIBS@
-nm_ca_dir = @nm_ca_dir@
-nm_plugins = @nm_plugins@
-oldincludedir = @oldincludedir@
-pcsclite_CFLAGS = @pcsclite_CFLAGS@
-pcsclite_LIBS = @pcsclite_LIBS@
-pdfdir = @pdfdir@
-piddir = @piddir@
-pkgpyexecdir = @pkgpyexecdir@
-pkgpythondir = @pkgpythondir@
-pki_plugins = @pki_plugins@
-plugindir = @plugindir@
-pool_plugins = @pool_plugins@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-pyexecdir = @pyexecdir@
-pythondir = @pythondir@
-random_device = @random_device@
-resolv_conf = @resolv_conf@
-routing_table = @routing_table@
-routing_table_prio = @routing_table_prio@
-s_plugins = @s_plugins@
-sbindir = @sbindir@
-scepclient_plugins = @scepclient_plugins@
-scripts_plugins = @scripts_plugins@
-sharedstatedir = @sharedstatedir@
-soup_CFLAGS = @soup_CFLAGS@
-soup_LIBS = @soup_LIBS@
-srcdir = @srcdir@
-starter_plugins = @starter_plugins@
-strongswan_conf = @strongswan_conf@
-strongswan_options = @strongswan_options@
-swanctldir = @swanctldir@
-sysconfdir = @sysconfdir@
-systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
-systemd_daemon_LIBS = @systemd_daemon_LIBS@
-systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
-systemd_journal_LIBS = @systemd_journal_LIBS@
-systemdsystemunitdir = @systemdsystemunitdir@
-t_plugins = @t_plugins@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-urandom_device = @urandom_device@
-xml_CFLAGS = @xml_CFLAGS@
-xml_LIBS = @xml_LIBS@
-AM_CPPFLAGS = \
-	-I${linux_headers} \
-	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra
-
-AM_CFLAGS = \
-	$(PLUGIN_CFLAGS)
-
- at MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-kernel-pfroute.la
- at MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-kernel-pfroute.la
-libstrongswan_kernel_pfroute_la_SOURCES = \
-	kernel_pfroute_plugin.h kernel_pfroute_plugin.c \
-	kernel_pfroute_net.h kernel_pfroute_net.c
-
-libstrongswan_kernel_pfroute_la_LDFLAGS = -module -avoid-version
-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 ) \
-	        && { if test -f $@; then exit 0; else break; fi; }; \
-	      exit 1;; \
-	  esac; \
-	done; \
-	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libhydra/plugins/kernel_pfroute/Makefile'; \
-	$(am__cd) $(top_srcdir) && \
-	  $(AUTOMAKE) --gnu src/libhydra/plugins/kernel_pfroute/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
-$(am__aclocal_m4_deps):
-
-clean-noinstLTLIBRARIES:
-	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-	@list='$(noinst_LTLIBRARIES)'; \
-	locs=`for p in $$list; do echo $$p; done | \
-	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
-	      sort -u`; \
-	test -z "$$locs" || { \
-	  echo rm -f $${locs}; \
-	  rm -f $${locs}; \
-	}
-
-install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
-	@$(NORMAL_INSTALL)
-	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
-	list2=; for p in $$list; do \
-	  if test -f $$p; then \
-	    list2="$$list2 $$p"; \
-	  else :; fi; \
-	done; \
-	test -z "$$list2" || { \
-	  echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
-	  $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
-	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
-	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
-	}
-
-uninstall-pluginLTLIBRARIES:
-	@$(NORMAL_UNINSTALL)
-	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
-	for p in $$list; do \
-	  $(am__strip_dir) \
-	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
-	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
-	done
-
-clean-pluginLTLIBRARIES:
-	-test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
-	@list='$(plugin_LTLIBRARIES)'; \
-	locs=`for p in $$list; do echo $$p; done | \
-	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
-	      sort -u`; \
-	test -z "$$locs" || { \
-	  echo rm -f $${locs}; \
-	  rm -f $${locs}; \
-	}
-
-libstrongswan-kernel-pfroute.la: $(libstrongswan_kernel_pfroute_la_OBJECTS) $(libstrongswan_kernel_pfroute_la_DEPENDENCIES) $(EXTRA_libstrongswan_kernel_pfroute_la_DEPENDENCIES) 
-	$(AM_V_CCLD)$(libstrongswan_kernel_pfroute_la_LINK) $(am_libstrongswan_kernel_pfroute_la_rpath) $(libstrongswan_kernel_pfroute_la_OBJECTS) $(libstrongswan_kernel_pfroute_la_LIBADD) $(LIBS)
-
-mostlyclean-compile:
-	-rm -f *.$(OBJEXT)
-
-distclean-compile:
-	-rm -f *.tab.c
-
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_pfroute_net.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_pfroute_plugin.Plo at am__quote@
-
-.c.o:
- at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
- at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
- at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ $<
-
-.c.obj:
- at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
- at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
- at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-
-.c.lo:
- at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
- at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
- at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LTCOMPILE) -c -o $@ $<
-
-mostlyclean-libtool:
-	-rm -f *.lo
-
-clean-libtool:
-	-rm -rf .libs _libs
-
-ID: $(am__tagged_files)
-	$(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-am
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-	set x; \
-	here=`pwd`; \
-	$(am__define_uniq_tagged_files); \
-	shift; \
-	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-	  test -n "$$unique" || unique=$$empty_fix; \
-	  if test $$# -gt 0; then \
-	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-	      "$$@" $$unique; \
-	  else \
-	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-	      $$unique; \
-	  fi; \
-	fi
-ctags: ctags-am
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-	$(am__define_uniq_tagged_files); \
-	test -z "$(CTAGS_ARGS)$$unique" \
-	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-	     $$unique
-
-GTAGS:
-	here=`$(am__cd) $(top_builddir) && pwd` \
-	  && $(am__cd) $(top_srcdir) \
-	  && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-am
-
-cscopelist-am: $(am__tagged_files)
-	list='$(am__tagged_files)'; \
-	case "$(srcdir)" in \
-	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
-	  *) sdir=$(subdir)/$(srcdir) ;; \
-	esac; \
-	for i in $$list; do \
-	  if test -f "$$i"; then \
-	    echo "$(subdir)/$$i"; \
-	  else \
-	    echo "$$sdir/$$i"; \
-	  fi; \
-	done >> $(top_builddir)/cscope.files
-
-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 "$(distdir)/$$file"; then \
-	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-	    fi; \
-	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-	    fi; \
-	    cp -fpR $$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:
-	if test -z '$(STRIP)'; then \
-	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-	      install; \
-	else \
-	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-	fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
-	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-noinstLTLIBRARIES \
-	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
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am: install-pluginLTLIBRARIES
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-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 TAGS all all-am check check-am clean clean-generic \
-	clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
-	cscopelist-am ctags ctags-am 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 tags-am 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/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c
deleted file mode 100644
index df80c29..0000000
--- a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c
+++ /dev/null
@@ -1,1903 +0,0 @@
-/*
- * Copyright (C) 2009-2013 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.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <ifaddrs.h>
-#include <net/route.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include "kernel_pfroute_net.h"
-
-#include <hydra.h>
-#include <utils/debug.h>
-#include <networking/host.h>
-#include <networking/tun_device.h>
-#include <threading/thread.h>
-#include <threading/mutex.h>
-#include <threading/condvar.h>
-#include <threading/rwlock.h>
-#include <threading/spinlock.h>
-#include <collections/hashtable.h>
-#include <collections/linked_list.h>
-#include <processing/jobs/callback_job.h>
-
-#ifndef HAVE_STRUCT_SOCKADDR_SA_LEN
-#error Cannot compile this plugin on systems where 'struct sockaddr' has no sa_len member.
-#endif
-
-/** properly align sockaddrs */
-#ifdef __APPLE__
-/* Apple always uses 4 bytes */
-#define SA_ALIGN 4
-#else
-/* while on other platforms like FreeBSD it depends on the architecture */
-#define SA_ALIGN sizeof(long)
-#endif
-#define SA_LEN(len) ((len) > 0 ? (((len)+SA_ALIGN-1) & ~(SA_ALIGN-1)) : SA_ALIGN)
-
-/** delay before firing roam events (ms) */
-#define ROAM_DELAY 100
-
-/** delay before reinstalling routes (ms) */
-#define ROUTE_DELAY 100
-
-typedef struct addr_entry_t addr_entry_t;
-
-/**
- * IP address in an inface_entry_t
- */
-struct addr_entry_t {
-
-	/** The ip address */
-	host_t *ip;
-
-	/** virtual IP managed by us */
-	bool virtual;
-};
-
-/**
- * destroy a addr_entry_t object
- */
-static void addr_entry_destroy(addr_entry_t *this)
-{
-	this->ip->destroy(this->ip);
-	free(this);
-}
-
-typedef struct iface_entry_t iface_entry_t;
-
-/**
- * A network interface on this system, containing addr_entry_t's
- */
-struct iface_entry_t {
-
-	/** interface index */
-	int ifindex;
-
-	/** name of the interface */
-	char ifname[IFNAMSIZ];
-
-	/** interface flags, as in netdevice(7) SIOCGIFFLAGS */
-	u_int flags;
-
-	/** list of addresses as host_t */
-	linked_list_t *addrs;
-
-	/** TRUE if usable by config */
-	bool usable;
-};
-
-/**
- * destroy an interface entry
- */
-static void iface_entry_destroy(iface_entry_t *this)
-{
-	this->addrs->destroy_function(this->addrs, (void*)addr_entry_destroy);
-	free(this);
-}
-
-/**
- * check if an interface is up
- */
-static inline bool iface_entry_up(iface_entry_t *iface)
-{
-	return (iface->flags & IFF_UP) == IFF_UP;
-}
-
-/**
- * check if an interface is up and usable
- */
-static inline bool iface_entry_up_and_usable(iface_entry_t *iface)
-{
-	return iface->usable && iface_entry_up(iface);
-}
-
-typedef struct addr_map_entry_t addr_map_entry_t;
-
-/**
- * Entry that maps an IP address to an interface entry
- */
-struct addr_map_entry_t {
-	/** The IP address */
-	host_t *ip;
-
-	/** The address entry for this IP address */
-	addr_entry_t *addr;
-
-	/** The interface this address is installed on */
-	iface_entry_t *iface;
-};
-
-/**
- * Hash a addr_map_entry_t object, all entries with the same IP address
- * are stored in the same bucket
- */
-static u_int addr_map_entry_hash(addr_map_entry_t *this)
-{
-	return chunk_hash(this->ip->get_address(this->ip));
-}
-
-/**
- * Compare two addr_map_entry_t objects, two entries are equal if they are
- * installed on the same interface
- */
-static bool addr_map_entry_equals(addr_map_entry_t *a, addr_map_entry_t *b)
-{
-	return a->iface->ifindex == b->iface->ifindex &&
-		   a->ip->ip_equals(a->ip, b->ip);
-}
-
-/**
- * Used with get_match this finds an address entry if it is installed on
- * an up and usable interface
- */
-static bool addr_map_entry_match_up_and_usable(addr_map_entry_t *a,
-											   addr_map_entry_t *b)
-{
-	return !b->addr->virtual && iface_entry_up_and_usable(b->iface) &&
-			a->ip->ip_equals(a->ip, b->ip);
-}
-
-/**
- * Used with get_match this finds an address entry if it is installed as virtual
- * IP address
- */
-static bool addr_map_entry_match_virtual(addr_map_entry_t *a, addr_map_entry_t *b)
-{
-	return b->addr->virtual && a->ip->ip_equals(a->ip, b->ip);
-}
-
-/**
- * Used with get_match this finds an address entry if it is installed on
- * any active local interface
- */
-static bool addr_map_entry_match_up(addr_map_entry_t *a, addr_map_entry_t *b)
-{
-	return !b->addr->virtual && iface_entry_up(b->iface) &&
-			a->ip->ip_equals(a->ip, b->ip);
-}
-
-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;
-
-	/** Gateway for this route */
-	host_t *gateway;
-
-	/** Destination net */
-	chunk_t dst_net;
-
-	/** Destination net prefixlen */
-	u_int8_t prefixlen;
-};
-
-/**
- * Clone a route_entry_t object.
- */
-static route_entry_t *route_entry_clone(route_entry_t *this)
-{
-	route_entry_t *route;
-
-	INIT(route,
-		.if_name = strdup(this->if_name),
-		.gateway = this->gateway ? this->gateway->clone(this->gateway) : NULL,
-		.dst_net = chunk_clone(this->dst_net),
-		.prefixlen = this->prefixlen,
-	);
-	return route;
-}
-
-/**
- * Destroy a route_entry_t object
- */
-static void route_entry_destroy(route_entry_t *this)
-{
-	free(this->if_name);
-	DESTROY_IF(this->gateway);
-	chunk_free(&this->dst_net);
-	free(this);
-}
-
-/**
- * Hash a route_entry_t object
- */
-static u_int route_entry_hash(route_entry_t *this)
-{
-	return chunk_hash_inc(chunk_from_thing(this->prefixlen),
-						  chunk_hash(this->dst_net));
-}
-
-/**
- * Compare two route_entry_t objects
- */
-static bool route_entry_equals(route_entry_t *a, route_entry_t *b)
-{
-	if (a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
-		chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen)
-	{
-		return (!a->gateway && !b->gateway) || (a->gateway && b->gateway &&
-					a->gateway->ip_equals(a->gateway, b->gateway));
-	}
-	return FALSE;
-}
-
-typedef struct net_change_t net_change_t;
-
-/**
- * Queued network changes
- */
-struct net_change_t {
-	/** Name of the interface that got activated (or an IP appeared on) */
-	char *if_name;
-};
-
-/**
- * Destroy a net_change_t object
- */
-static void net_change_destroy(net_change_t *this)
-{
-	free(this->if_name);
-	free(this);
-}
-
-/**
- * Hash a net_change_t object
- */
-static u_int net_change_hash(net_change_t *this)
-{
-	return chunk_hash(chunk_create(this->if_name, strlen(this->if_name)));
-}
-
-/**
- * Compare two net_change_t objects
- */
-static bool net_change_equals(net_change_t *a, net_change_t *b)
-{
-	return streq(a->if_name, b->if_name);
-}
-
-typedef struct private_kernel_pfroute_net_t private_kernel_pfroute_net_t;
-
-/**
- * Private variables and functions of kernel_pfroute class.
- */
-struct private_kernel_pfroute_net_t
-{
-	/**
-	 * Public part of the kernel_pfroute_t object.
-	 */
-	kernel_pfroute_net_t public;
-
-	/**
-	 * lock to access lists and maps
-	 */
-	rwlock_t *lock;
-
-	/**
-	 * Cached list of interfaces and their addresses (iface_entry_t)
-	 */
-	linked_list_t *ifaces;
-
-	/**
-	 * Map for IP addresses to iface_entry_t objects (addr_map_entry_t)
-	 */
-	hashtable_t *addrs;
-
-	/**
-	 * List of tun devices we installed for virtual IPs
-	 */
-	linked_list_t *tuns;
-
-	/**
-	 * mutex to communicate exclusively with PF_KEY
-	 */
-	mutex_t *mutex;
-
-	/**
-	 * condvar to signal if PF_KEY query got a response
-	 */
-	condvar_t *condvar;
-
-	/**
-	 * installed routes
-	 */
-	hashtable_t *routes;
-
-	/**
-	 * mutex for routes
-	 */
-	mutex_t *routes_lock;
-
-	/**
-	 * interface changes which may trigger route reinstallation
-	 */
-	hashtable_t *net_changes;
-
-	/**
-	 * mutex for route reinstallation triggers
-	 */
-	mutex_t *net_changes_lock;
-
-	/**
-	 * time of last route reinstallation
-	 */
-	timeval_t last_route_reinstall;
-
-	/**
-	 * pid to send PF_ROUTE messages with
-	 */
-	pid_t pid;
-
-	/**
-	 * PF_ROUTE socket to communicate with the kernel
-	 */
-	int socket;
-
-	/**
-	 * sequence number for messages sent to the kernel
-	 */
-	int seq;
-
-	/**
-	 * Sequence number a query is waiting for
-	 */
-	int waiting_seq;
-
-	/**
-	 * Allocated reply message from kernel
-	 */
-	struct rt_msghdr *reply;
-
-	/**
-	 * earliest time of the next roam event
-	 */
-	timeval_t next_roam;
-
-	/**
-	 * roam event due to address change
-	 */
-	bool roam_address;
-
-	/**
-	 * lock to check and update roam event time
-	 */
-	spinlock_t *roam_lock;
-
-	/**
-	 * Time in ms to wait for IP addresses to appear/disappear
-	 */
-	int vip_wait;
-
-	/**
-	 * whether to actually install virtual IPs
-	 */
-	bool install_virtual_ip;
-};
-
-
-/**
- * Forward declaration
- */
-static status_t manage_route(private_kernel_pfroute_net_t *this, int op,
-							 chunk_t dst_net, u_int8_t prefixlen,
-							 host_t *gateway, char *if_name);
-
-/**
- * Clear the queued network changes.
- */
-static void net_changes_clear(private_kernel_pfroute_net_t *this)
-{
-	enumerator_t *enumerator;
-	net_change_t *change;
-
-	enumerator = this->net_changes->create_enumerator(this->net_changes);
-	while (enumerator->enumerate(enumerator, NULL, (void**)&change))
-	{
-		this->net_changes->remove_at(this->net_changes, enumerator);
-		net_change_destroy(change);
-	}
-	enumerator->destroy(enumerator);
-}
-
-/**
- * Act upon queued network changes.
- */
-static job_requeue_t reinstall_routes(private_kernel_pfroute_net_t *this)
-{
-	enumerator_t *enumerator;
-	route_entry_t *route;
-
-	this->net_changes_lock->lock(this->net_changes_lock);
-	this->routes_lock->lock(this->routes_lock);
-
-	enumerator = this->routes->create_enumerator(this->routes);
-	while (enumerator->enumerate(enumerator, NULL, (void**)&route))
-	{
-		net_change_t *change, lookup = {
-			.if_name = route->if_name,
-		};
-		/* check if a change for the outgoing interface is queued */
-		change = this->net_changes->get(this->net_changes, &lookup);
-		if (change)
-		{
-			manage_route(this, RTM_ADD, route->dst_net, route->prefixlen,
-						 route->gateway, route->if_name);
-		}
-	}
-	enumerator->destroy(enumerator);
-	this->routes_lock->unlock(this->routes_lock);
-
-	net_changes_clear(this);
-	this->net_changes_lock->unlock(this->net_changes_lock);
-	return JOB_REQUEUE_NONE;
-}
-
-/**
- * Queue route reinstallation caused by network changes for a given interface.
- *
- * The route reinstallation is delayed for a while and only done once for
- * several calls during this delay, in order to avoid doing it too often.
- * The interface name is freed.
- */
-static void queue_route_reinstall(private_kernel_pfroute_net_t *this,
-								  char *if_name)
-{
-	net_change_t *update, *found;
-	timeval_t now;
-	job_t *job;
-
-	INIT(update,
-		.if_name = if_name
-	);
-
-	this->net_changes_lock->lock(this->net_changes_lock);
-	found = this->net_changes->put(this->net_changes, update, update);
-	if (found)
-	{
-		net_change_destroy(found);
-	}
-	time_monotonic(&now);
-	if (timercmp(&now, &this->last_route_reinstall, >))
-	{
-		timeval_add_ms(&now, ROUTE_DELAY);
-		this->last_route_reinstall = now;
-
-		job = (job_t*)callback_job_create((callback_job_cb_t)reinstall_routes,
-										  this, NULL, NULL);
-		lib->scheduler->schedule_job_ms(lib->scheduler, job, ROUTE_DELAY);
-	}
-	this->net_changes_lock->unlock(this->net_changes_lock);
-}
-
-/**
- * Add an address map entry
- */
-static void addr_map_entry_add(private_kernel_pfroute_net_t *this,
-							   addr_entry_t *addr, iface_entry_t *iface)
-{
-	addr_map_entry_t *entry;
-
-	INIT(entry,
-		.ip = addr->ip,
-		.addr = addr,
-		.iface = iface,
-	);
-	entry = this->addrs->put(this->addrs, entry, entry);
-	free(entry);
-}
-
-/**
- * Remove an address map entry (the argument order is a bit strange because
- * it is also used with linked_list_t.invoke_function)
- */
-static void addr_map_entry_remove(addr_entry_t *addr, iface_entry_t *iface,
-								  private_kernel_pfroute_net_t *this)
-{
-	addr_map_entry_t *entry, lookup = {
-		.ip = addr->ip,
-		.addr = addr,
-		.iface = iface,
-	};
-
-	entry = this->addrs->remove(this->addrs, &lookup);
-	free(entry);
-}
-
-/**
- * callback function that raises the delayed roam event
- */
-static job_requeue_t roam_event(private_kernel_pfroute_net_t *this)
-{
-	bool address;
-
-	this->roam_lock->lock(this->roam_lock);
-	address = this->roam_address;
-	this->roam_address = FALSE;
-	this->roam_lock->unlock(this->roam_lock);
-	hydra->kernel_interface->roam(hydra->kernel_interface, address);
-	return JOB_REQUEUE_NONE;
-}
-
-/**
- * fire a roaming event. we delay it for a bit and fire only one event
- * for multiple calls. otherwise we would create too many events.
- */
-static void fire_roam_event(private_kernel_pfroute_net_t *this, bool address)
-{
-	timeval_t now;
-	job_t *job;
-
-	time_monotonic(&now);
-	this->roam_lock->lock(this->roam_lock);
-	this->roam_address |= address;
-	if (!timercmp(&now, &this->next_roam, >))
-	{
-		this->roam_lock->unlock(this->roam_lock);
-		return;
-	}
-	timeval_add_ms(&now, ROAM_DELAY);
-	this->next_roam = now;
-	this->roam_lock->unlock(this->roam_lock);
-
-	job = (job_t*)callback_job_create((callback_job_cb_t)roam_event,
-									  this, NULL, NULL);
-	lib->scheduler->schedule_job_ms(lib->scheduler, job, ROAM_DELAY);
-}
-
-/**
- * Data for enumerator over rtmsg sockaddrs
- */
-typedef struct {
-	/** implements enumerator */
-	enumerator_t public;
-	/** copy of attribute bitfield */
-	int types;
-	/** bytes remaining in buffer */
-	int remaining;
-	/** next sockaddr to enumerate */
-	struct sockaddr *addr;
-} rt_enumerator_t;
-
-METHOD(enumerator_t, rt_enumerate, bool,
-	rt_enumerator_t *this, int *xtype, struct sockaddr **addr)
-{
-	int i, type;
-
-	if (this->remaining < sizeof(this->addr->sa_len) ||
-		this->remaining < this->addr->sa_len)
-	{
-		return FALSE;
-	}
-	for (i = 0; i < RTAX_MAX; i++)
-	{
-		type = (1 << i);
-		if (this->types & type)
-		{
-			this->types &= ~type;
-			*addr = this->addr;
-			*xtype = i;
-			this->remaining -= SA_LEN(this->addr->sa_len);
-			this->addr = (struct sockaddr*)((char*)this->addr +
-											SA_LEN(this->addr->sa_len));
-			return TRUE;
-		}
-	}
-	return FALSE;
-}
-
-/**
- * Create an enumerator over sockaddrs in rt/if messages
- */
-static enumerator_t *create_rt_enumerator(int types, int remaining,
-										  struct sockaddr *addr)
-{
-	rt_enumerator_t *this;
-
-	INIT(this,
-		.public = {
-			.enumerate = (void*)_rt_enumerate,
-			.destroy = (void*)free,
-		},
-		.types = types,
-		.remaining = remaining,
-		.addr = addr,
-	);
-	return &this->public;
-}
-
-/**
- * Create a safe enumerator over sockaddrs in rt_msghdr
- */
-static enumerator_t *create_rtmsg_enumerator(struct rt_msghdr *hdr)
-{
-	return create_rt_enumerator(hdr->rtm_addrs, hdr->rtm_msglen - sizeof(*hdr),
-								(struct sockaddr *)(hdr + 1));
-}
-
-/**
- * Create a safe enumerator over sockaddrs in ifa_msghdr
- */
-static enumerator_t *create_ifamsg_enumerator(struct ifa_msghdr *hdr)
-{
-	return create_rt_enumerator(hdr->ifam_addrs, hdr->ifam_msglen - sizeof(*hdr),
-								(struct sockaddr *)(hdr + 1));
-}
-
-/**
- * Process an RTM_*ADDR message from the kernel
- */
-static void process_addr(private_kernel_pfroute_net_t *this,
-						 struct ifa_msghdr *ifa)
-{
-	struct sockaddr *sockaddr;
-	host_t *host = NULL;
-	enumerator_t *ifaces, *addrs;
-	iface_entry_t *iface;
-	addr_entry_t *addr;
-	bool found = FALSE, changed = FALSE, roam = FALSE;
-	enumerator_t *enumerator;
-	char *ifname = NULL;
-	int type;
-
-	enumerator = create_ifamsg_enumerator(ifa);
-	while (enumerator->enumerate(enumerator, &type, &sockaddr))
-	{
-		if (type == RTAX_IFA)
-		{
-			host = host_create_from_sockaddr(sockaddr);
-			break;
-		}
-	}
-	enumerator->destroy(enumerator);
-
-	if (!host || host->is_anyaddr(host))
-	{
-		DESTROY_IF(host);
-		return;
-	}
-
-	this->lock->write_lock(this->lock);
-	ifaces = this->ifaces->create_enumerator(this->ifaces);
-	while (ifaces->enumerate(ifaces, &iface))
-	{
-		if (iface->ifindex == ifa->ifam_index)
-		{
-			addrs = iface->addrs->create_enumerator(iface->addrs);
-			while (addrs->enumerate(addrs, &addr))
-			{
-				if (host->ip_equals(host, addr->ip))
-				{
-					found = TRUE;
-					if (ifa->ifam_type == RTM_DELADDR)
-					{
-						iface->addrs->remove_at(iface->addrs, addrs);
-						if (!addr->virtual && iface->usable)
-						{
-							changed = TRUE;
-							DBG1(DBG_KNL, "%H disappeared from %s",
-								 host, iface->ifname);
-						}
-						addr_map_entry_remove(addr, iface, this);
-						addr_entry_destroy(addr);
-					}
-				}
-			}
-			addrs->destroy(addrs);
-
-			if (!found && ifa->ifam_type == RTM_NEWADDR)
-			{
-				INIT(addr,
-					.ip = host->clone(host),
-				);
-				changed = TRUE;
-				ifname = strdup(iface->ifname);
-				iface->addrs->insert_last(iface->addrs, addr);
-				addr_map_entry_add(this, addr, iface);
-				if (iface->usable)
-				{
-					DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
-				}
-			}
-
-			if (changed && iface_entry_up_and_usable(iface))
-			{
-				roam = TRUE;
-			}
-			break;
-		}
-	}
-	ifaces->destroy(ifaces);
-	this->lock->unlock(this->lock);
-	host->destroy(host);
-
-	if (roam && ifname)
-	{
-		queue_route_reinstall(this, ifname);
-	}
-	else
-	{
-		free(ifname);
-	}
-
-	if (roam)
-	{
-		fire_roam_event(this, TRUE);
-	}
-}
-
-/**
- * Re-initialize address list of an interface if it changes state
- */
-static void repopulate_iface(private_kernel_pfroute_net_t *this,
-							 iface_entry_t *iface)
-{
-	struct ifaddrs *ifap, *ifa;
-	addr_entry_t *addr;
-
-	while (iface->addrs->remove_last(iface->addrs, (void**)&addr) == SUCCESS)
-	{
-		addr_map_entry_remove(addr, iface, this);
-		addr_entry_destroy(addr);
-	}
-
-	if (getifaddrs(&ifap) == 0)
-	{
-		for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
-		{
-			if (ifa->ifa_addr && streq(ifa->ifa_name, iface->ifname))
-			{
-				switch (ifa->ifa_addr->sa_family)
-				{
-					case AF_INET:
-					case AF_INET6:
-						INIT(addr,
-							.ip = host_create_from_sockaddr(ifa->ifa_addr),
-						);
-						iface->addrs->insert_last(iface->addrs, addr);
-						addr_map_entry_add(this, addr, iface);
-						break;
-					default:
-						break;
-				}
-			}
-		}
-		freeifaddrs(ifap);
-	}
-}
-
-/**
- * Process an RTM_IFINFO message from the kernel
- */
-static void process_link(private_kernel_pfroute_net_t *this,
-						 struct if_msghdr *msg)
-{
-	enumerator_t *enumerator;
-	iface_entry_t *iface;
-	bool roam = FALSE, found = FALSE, update_routes = FALSE;
-
-	this->lock->write_lock(this->lock);
-	enumerator = this->ifaces->create_enumerator(this->ifaces);
-	while (enumerator->enumerate(enumerator, &iface))
-	{
-		if (iface->ifindex == msg->ifm_index)
-		{
-			if (iface->usable)
-			{
-				if (!(iface->flags & IFF_UP) && (msg->ifm_flags & IFF_UP))
-				{
-					roam = update_routes = TRUE;
-					DBG1(DBG_KNL, "interface %s activated", iface->ifname);
-				}
-				else if ((iface->flags & IFF_UP) && !(msg->ifm_flags & IFF_UP))
-				{
-					roam = TRUE;
-					DBG1(DBG_KNL, "interface %s deactivated", iface->ifname);
-				}
-			}
-#ifdef __APPLE__
-			/* There seems to be a race condition on 10.10, where we get
-			 * the RTM_IFINFO, but getifaddrs() does not return the virtual
-			 * IP installed on a tun device, but we also don't get a
-			 * RTM_NEWADDR. We therefore could miss the new address, letting
-			 * virtual IP installation fail. Delaying getifaddrs() helps,
-			 * but is obviously not a clean fix. */
-			usleep(50000);
-#endif
-			iface->flags = msg->ifm_flags;
-			repopulate_iface(this, iface);
-			found = TRUE;
-			break;
-		}
-	}
-	enumerator->destroy(enumerator);
-
-	if (!found)
-	{
-		INIT(iface,
-			.ifindex = msg->ifm_index,
-			.flags = msg->ifm_flags,
-			.addrs = linked_list_create(),
-		);
-		if (if_indextoname(iface->ifindex, iface->ifname))
-		{
-			DBG1(DBG_KNL, "interface %s appeared", iface->ifname);
-			iface->usable = hydra->kernel_interface->is_interface_usable(
-										hydra->kernel_interface, iface->ifname);
-			repopulate_iface(this, iface);
-			this->ifaces->insert_last(this->ifaces, iface);
-			if (iface->usable)
-			{
-				roam = update_routes = TRUE;
-			}
-		}
-		else
-		{
-			free(iface);
-		}
-	}
-	this->lock->unlock(this->lock);
-
-	if (update_routes)
-	{
-		queue_route_reinstall(this, strdup(iface->ifname));
-	}
-
-	if (roam)
-	{
-		fire_roam_event(this, TRUE);
-	}
-}
-
-#ifdef HAVE_RTM_IFANNOUNCE
-
-/**
- * Process an RTM_IFANNOUNCE message from the kernel
- */
-static void process_announce(private_kernel_pfroute_net_t *this,
-							 struct if_announcemsghdr *msg)
-{
-	enumerator_t *enumerator;
-	iface_entry_t *iface;
-
-	if (msg->ifan_what != IFAN_DEPARTURE)
-	{
-		/* we handle new interfaces in process_link() */
-		return;
-	}
-
-	this->lock->write_lock(this->lock);
-	enumerator = this->ifaces->create_enumerator(this->ifaces);
-	while (enumerator->enumerate(enumerator, &iface))
-	{
-		if (iface->ifindex == msg->ifan_index)
-		{
-			DBG1(DBG_KNL, "interface %s disappeared", iface->ifname);
-			this->ifaces->remove_at(this->ifaces, enumerator);
-			iface_entry_destroy(iface);
-			break;
-		}
-	}
-	enumerator->destroy(enumerator);
-	this->lock->unlock(this->lock);
-}
-
-#endif /* HAVE_RTM_IFANNOUNCE */
-
-/**
- * Process an RTM_*ROUTE message from the kernel
- */
-static void process_route(private_kernel_pfroute_net_t *this,
-						  struct rt_msghdr *msg)
-{
-
-}
-
-/**
- * Receives PF_ROUTE messages from kernel
- */
-static bool receive_events(private_kernel_pfroute_net_t *this, int fd,
-						   watcher_event_t event)
-{
-	struct {
-		union {
-			struct rt_msghdr rtm;
-			struct if_msghdr ifm;
-			struct ifa_msghdr ifam;
-#ifdef HAVE_RTM_IFANNOUNCE
-			struct if_announcemsghdr ifanm;
-#endif
-		};
-		char buf[sizeof(struct sockaddr_storage) * RTAX_MAX];
-	} msg;
-	int len, hdrlen;
-
-	len = recv(this->socket, &msg, sizeof(msg), MSG_DONTWAIT);
-	if (len < 0)
-	{
-		switch (errno)
-		{
-			case EINTR:
-			case EAGAIN:
-				return TRUE;
-			default:
-				DBG1(DBG_KNL, "unable to receive from PF_ROUTE event socket");
-				sleep(1);
-				return TRUE;
-		}
-	}
-
-	if (len < offsetof(struct rt_msghdr, rtm_flags) || len < msg.rtm.rtm_msglen)
-	{
-		DBG1(DBG_KNL, "received invalid PF_ROUTE message");
-		return TRUE;
-	}
-	if (msg.rtm.rtm_version != RTM_VERSION)
-	{
-		DBG1(DBG_KNL, "received PF_ROUTE message with unsupported version: %d",
-			 msg.rtm.rtm_version);
-		return TRUE;
-	}
-	switch (msg.rtm.rtm_type)
-	{
-		case RTM_NEWADDR:
-		case RTM_DELADDR:
-			hdrlen = sizeof(msg.ifam);
-			break;
-		case RTM_IFINFO:
-			hdrlen = sizeof(msg.ifm);
-			break;
-#ifdef HAVE_RTM_IFANNOUNCE
-		case RTM_IFANNOUNCE:
-			hdrlen = sizeof(msg.ifanm);
-			break;
-#endif /* HAVE_RTM_IFANNOUNCE */
-		case RTM_ADD:
-		case RTM_DELETE:
-		case RTM_GET:
-			hdrlen = sizeof(msg.rtm);
-			break;
-		default:
-			return TRUE;
-	}
-	if (msg.rtm.rtm_msglen < hdrlen)
-	{
-		DBG1(DBG_KNL, "ignoring short PF_ROUTE message");
-		return TRUE;
-	}
-	switch (msg.rtm.rtm_type)
-	{
-		case RTM_NEWADDR:
-		case RTM_DELADDR:
-			process_addr(this, &msg.ifam);
-			break;
-		case RTM_IFINFO:
-			process_link(this, &msg.ifm);
-			break;
-#ifdef HAVE_RTM_IFANNOUNCE
-		case RTM_IFANNOUNCE:
-			process_announce(this, &msg.ifanm);
-			break;
-#endif /* HAVE_RTM_IFANNOUNCE */
-		case RTM_ADD:
-		case RTM_DELETE:
-			process_route(this, &msg.rtm);
-			break;
-		default:
-			break;
-	}
-
-	this->mutex->lock(this->mutex);
-	if (msg.rtm.rtm_pid == this->pid && msg.rtm.rtm_seq == this->waiting_seq)
-	{
-		/* seems like the message someone is waiting for, deliver */
-		this->reply = realloc(this->reply, msg.rtm.rtm_msglen);
-		memcpy(this->reply, &msg, msg.rtm.rtm_msglen);
-	}
-	/* signal on any event, add_ip()/del_ip() might wait for it */
-	this->condvar->broadcast(this->condvar);
-	this->mutex->unlock(this->mutex);
-
-	return TRUE;
-}
-
-
-/** enumerator over addresses */
-typedef struct {
-	private_kernel_pfroute_net_t* this;
-	/** which addresses to enumerate */
-	kernel_address_type_t which;
-} address_enumerator_t;
-
-/**
- * cleanup function for address enumerator
- */
-static void address_enumerator_destroy(address_enumerator_t *data)
-{
-	data->this->lock->unlock(data->this->lock);
-	free(data);
-}
-
-/**
- * filter for addresses
- */
-static bool filter_addresses(address_enumerator_t *data,
-							 addr_entry_t** in, host_t** out)
-{
-	host_t *ip;
-	if (!(data->which & ADDR_TYPE_VIRTUAL) && (*in)->virtual)
-	{   /* skip virtual interfaces added by us */
-		return FALSE;
-	}
-	if (!(data->which & ADDR_TYPE_REGULAR) && !(*in)->virtual)
-	{	/* address is regular, but not requested */
-		return FALSE;
-	}
-	ip = (*in)->ip;
-	if (ip->get_family(ip) == AF_INET6)
-	{
-		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ip->get_sockaddr(ip);
-		if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
-		{   /* skip addresses with a unusable scope */
-			return FALSE;
-		}
-	}
-	*out = ip;
-	return TRUE;
-}
-
-/**
- * enumerator constructor for interfaces
- */
-static enumerator_t *create_iface_enumerator(iface_entry_t *iface,
-											 address_enumerator_t *data)
-{
-	return enumerator_create_filter(iface->addrs->create_enumerator(iface->addrs),
-									(void*)filter_addresses, data, NULL);
-}
-
-/**
- * filter for interfaces
- */
-static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in,
-							  iface_entry_t** out)
-{
-	if (!(data->which & ADDR_TYPE_IGNORED) && !(*in)->usable)
-	{	/* skip interfaces excluded by config */
-		return FALSE;
-	}
-	if (!(data->which & ADDR_TYPE_LOOPBACK) && ((*in)->flags & IFF_LOOPBACK))
-	{	/* ignore loopback devices */
-		return FALSE;
-	}
-	if (!(data->which & ADDR_TYPE_DOWN) && !((*in)->flags & IFF_UP))
-	{	/* skip interfaces not up */
-		return FALSE;
-	}
-	*out = *in;
-	return TRUE;
-}
-
-METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
-	private_kernel_pfroute_net_t *this, kernel_address_type_t which)
-{
-	address_enumerator_t *data;
-
-	INIT(data,
-		.this = this,
-		.which = which,
-	);
-
-	this->lock->read_lock(this->lock);
-	return enumerator_create_nested(
-				enumerator_create_filter(
-					this->ifaces->create_enumerator(this->ifaces),
-					(void*)filter_interfaces, data, NULL),
-				(void*)create_iface_enumerator, data,
-				(void*)address_enumerator_destroy);
-}
-
-METHOD(kernel_net_t, get_features, kernel_feature_t,
-	private_kernel_pfroute_net_t *this)
-{
-	return KERNEL_REQUIRE_EXCLUDE_ROUTE;
-}
-
-METHOD(kernel_net_t, get_interface_name, bool,
-	private_kernel_pfroute_net_t *this, host_t* ip, char **name)
-{
-	addr_map_entry_t *entry, lookup = {
-		.ip = ip,
-	};
-
-	if (ip->is_anyaddr(ip))
-	{
-		return FALSE;
-	}
-	this->lock->read_lock(this->lock);
-	/* first try to find it on an up and usable interface */
-	entry = this->addrs->get_match(this->addrs, &lookup,
-								  (void*)addr_map_entry_match_up_and_usable);
-	if (entry)
-	{
-		if (name)
-		{
-			*name = strdup(entry->iface->ifname);
-			DBG2(DBG_KNL, "%H is on interface %s", ip, *name);
-		}
-		this->lock->unlock(this->lock);
-		return TRUE;
-	}
-	/* check if it is a virtual IP */
-	entry = this->addrs->get_match(this->addrs, &lookup,
-								  (void*)addr_map_entry_match_virtual);
-	if (entry)
-	{
-		if (name)
-		{
-			*name = strdup(entry->iface->ifname);
-			DBG2(DBG_KNL, "virtual IP %H is on interface %s", ip, *name);
-		}
-		this->lock->unlock(this->lock);
-		return TRUE;
-	}
-	/* maybe it is installed on an ignored interface */
-	entry = this->addrs->get_match(this->addrs, &lookup,
-								  (void*)addr_map_entry_match_up);
-	if (!entry)
-	{	/* the address does not exist, is on a down interface */
-		DBG2(DBG_KNL, "%H is not a local address or the interface is down", ip);
-	}
-	this->lock->unlock(this->lock);
-	return FALSE;
-}
-
-METHOD(kernel_net_t, add_ip, status_t,
-	private_kernel_pfroute_net_t *this, host_t *vip, int prefix,
-	char *ifname)
-{
-	enumerator_t *ifaces, *addrs;
-	iface_entry_t *iface;
-	addr_entry_t *addr;
-	tun_device_t *tun;
-	bool timeout = FALSE;
-
-	if (!this->install_virtual_ip)
-	{	/* disabled by config */
-		return SUCCESS;
-	}
-
-	tun = tun_device_create(NULL);
-	if (!tun)
-	{
-		return FAILED;
-	}
-	if (prefix == -1)
-	{
-		prefix = vip->get_address(vip).len * 8;
-	}
-	if (!tun->up(tun) || !tun->set_address(tun, vip, prefix))
-	{
-		tun->destroy(tun);
-		return FAILED;
-	}
-
-	/* wait until address appears */
-	this->mutex->lock(this->mutex);
-	while (!timeout && !get_interface_name(this, vip, NULL))
-	{
-		timeout = this->condvar->timed_wait(this->condvar, this->mutex,
-											this->vip_wait);
-	}
-	this->mutex->unlock(this->mutex);
-	if (timeout)
-	{
-		DBG1(DBG_KNL, "virtual IP %H did not appear on %s",
-			 vip, tun->get_name(tun));
-		tun->destroy(tun);
-		return FAILED;
-	}
-
-	this->lock->write_lock(this->lock);
-	this->tuns->insert_last(this->tuns, tun);
-
-	ifaces = this->ifaces->create_enumerator(this->ifaces);
-	while (ifaces->enumerate(ifaces, &iface))
-	{
-		if (streq(iface->ifname, tun->get_name(tun)))
-		{
-			addrs = iface->addrs->create_enumerator(iface->addrs);
-			while (addrs->enumerate(addrs, &addr))
-			{
-				if (addr->ip->ip_equals(addr->ip, vip))
-				{
-					addr->virtual = TRUE;
-				}
-			}
-			addrs->destroy(addrs);
-			/* during IKEv1 reauthentication, children get moved from
-			 * old the new SA before the virtual IP is available. This
-			 * kills the route for our virtual IP, reinstall. */
-			queue_route_reinstall(this, strdup(iface->ifname));
-			break;
-		}
-	}
-	ifaces->destroy(ifaces);
-	/* lets do this while holding the lock, thus preventing another thread
-	 * from deleting the TUN device concurrently, hopefully listeners are quick
-	 * and cause no deadlocks */
-	hydra->kernel_interface->tun(hydra->kernel_interface, tun, TRUE);
-	this->lock->unlock(this->lock);
-
-	return SUCCESS;
-}
-
-METHOD(kernel_net_t, del_ip, status_t,
-	private_kernel_pfroute_net_t *this, host_t *vip, int prefix,
-	bool wait)
-{
-	enumerator_t *enumerator;
-	tun_device_t *tun;
-	host_t *addr;
-	bool timeout = FALSE, found = FALSE;
-
-	if (!this->install_virtual_ip)
-	{	/* disabled by config */
-		return SUCCESS;
-	}
-
-	this->lock->write_lock(this->lock);
-	enumerator = this->tuns->create_enumerator(this->tuns);
-	while (enumerator->enumerate(enumerator, &tun))
-	{
-		addr = tun->get_address(tun, NULL);
-		if (addr && addr->ip_equals(addr, vip))
-		{
-			this->tuns->remove_at(this->tuns, enumerator);
-			hydra->kernel_interface->tun(hydra->kernel_interface, tun,
-										 FALSE);
-			tun->destroy(tun);
-			found = TRUE;
-			break;
-		}
-	}
-	enumerator->destroy(enumerator);
-	this->lock->unlock(this->lock);
-
-	if (!found)
-	{
-		return NOT_FOUND;
-	}
-	/* wait until address disappears */
-	if (wait)
-	{
-		this->mutex->lock(this->mutex);
-		while (!timeout && get_interface_name(this, vip, NULL))
-		{
-			timeout = this->condvar->timed_wait(this->condvar, this->mutex,
-												this->vip_wait);
-		}
-		this->mutex->unlock(this->mutex);
-		if (timeout)
-		{
-			DBG1(DBG_KNL, "virtual IP %H did not disappear from tun", vip);
-			return FAILED;
-		}
-	}
-	return SUCCESS;
-}
-
-/**
- * Append a sockaddr_in/in6 of given type to routing message
- */
-static void add_rt_addr(struct rt_msghdr *hdr, int type, host_t *addr)
-{
-	if (addr)
-	{
-		int len;
-
-		len = *addr->get_sockaddr_len(addr);
-		memcpy((char*)hdr + hdr->rtm_msglen, addr->get_sockaddr(addr), len);
-		hdr->rtm_msglen += SA_LEN(len);
-		hdr->rtm_addrs |= type;
-	}
-}
-
-/**
- * Append a subnet mask sockaddr using the given prefix to routing message
- */
-static void add_rt_mask(struct rt_msghdr *hdr, int type, int family, int prefix)
-{
-	host_t *mask;
-
-	mask = host_create_netmask(family, prefix);
-	if (mask)
-	{
-		add_rt_addr(hdr, type, mask);
-		mask->destroy(mask);
-	}
-}
-
-/**
- * Append an interface name sockaddr_dl to routing message
- */
-static void add_rt_ifname(struct rt_msghdr *hdr, int type, char *name)
-{
-	struct sockaddr_dl sdl = {
-		.sdl_len = sizeof(struct sockaddr_dl),
-		.sdl_family = AF_LINK,
-		.sdl_nlen = strlen(name),
-	};
-
-	if (strlen(name) <= sizeof(sdl.sdl_data))
-	{
-		memcpy(sdl.sdl_data, name, sdl.sdl_nlen);
-		memcpy((char*)hdr + hdr->rtm_msglen, &sdl, sdl.sdl_len);
-		hdr->rtm_msglen += SA_LEN(sdl.sdl_len);
-		hdr->rtm_addrs |= type;
-	}
-}
-
-/**
- * Add or remove a route
- */
-static status_t manage_route(private_kernel_pfroute_net_t *this, int op,
-							 chunk_t dst_net, u_int8_t prefixlen,
-							 host_t *gateway, char *if_name)
-{
-	struct {
-		struct rt_msghdr hdr;
-		char buf[sizeof(struct sockaddr_storage) * RTAX_MAX];
-	} msg = {
-		.hdr = {
-			.rtm_version = RTM_VERSION,
-			.rtm_type = op,
-			.rtm_flags = RTF_UP | RTF_STATIC,
-			.rtm_pid = this->pid,
-			.rtm_seq = ref_get(&this->seq),
-		},
-	};
-	host_t *dst;
-	int type;
-
-	if (prefixlen == 0 && dst_net.len)
-	{
-		status_t status;
-		chunk_t half;
-
-		half = chunk_clonea(dst_net);
-		half.ptr[0] |= 0x80;
-		prefixlen = 1;
-		status = manage_route(this, op, half, prefixlen, gateway, if_name);
-		if (status != SUCCESS)
-		{
-			return status;
-		}
-	}
-
-	dst = host_create_from_chunk(AF_UNSPEC, dst_net, 0);
-	if (!dst)
-	{
-		return FAILED;
-	}
-
-	if ((dst->get_family(dst) == AF_INET && prefixlen == 32) ||
-		(dst->get_family(dst) == AF_INET6 && prefixlen == 128))
-	{
-		msg.hdr.rtm_flags |= RTF_HOST | RTF_GATEWAY;
-	}
-
-	msg.hdr.rtm_msglen = sizeof(struct rt_msghdr);
-	for (type = 0; type < RTAX_MAX; type++)
-	{
-		switch (type)
-		{
-			case RTAX_DST:
-				add_rt_addr(&msg.hdr, RTA_DST, dst);
-				break;
-			case RTAX_NETMASK:
-				if (!(msg.hdr.rtm_flags & RTF_HOST))
-				{
-					add_rt_mask(&msg.hdr, RTA_NETMASK,
-								dst->get_family(dst), prefixlen);
-				}
-				break;
-			case RTAX_IFP:
-				if (if_name)
-				{
-					add_rt_ifname(&msg.hdr, RTA_IFP, if_name);
-				}
-				break;
-			case RTAX_GATEWAY:
-				if (gateway)
-				{
-					add_rt_addr(&msg.hdr, RTA_GATEWAY, gateway);
-				}
-				break;
-			default:
-				break;
-		}
-	}
-	dst->destroy(dst);
-
-	if (send(this->socket, &msg, msg.hdr.rtm_msglen, 0) != msg.hdr.rtm_msglen)
-	{
-		if (errno == EEXIST)
-		{
-			return ALREADY_DONE;
-		}
-		DBG1(DBG_KNL, "%s PF_ROUTE route failed: %s",
-			 op == RTM_ADD ? "adding" : "deleting", strerror(errno));
-		return FAILED;
-	}
-	return SUCCESS;
-}
-
-METHOD(kernel_net_t, add_route, status_t,
-	private_kernel_pfroute_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
-	host_t *gateway, host_t *src_ip, char *if_name)
-{
-	status_t status;
-	route_entry_t *found, route = {
-		.dst_net = dst_net,
-		.prefixlen = prefixlen,
-		.gateway = gateway,
-		.if_name = if_name,
-	};
-
-	this->routes_lock->lock(this->routes_lock);
-	found = this->routes->get(this->routes, &route);
-	if (found)
-	{
-		this->routes_lock->unlock(this->routes_lock);
-		return ALREADY_DONE;
-	}
-	status = manage_route(this, RTM_ADD, dst_net, prefixlen, gateway, if_name);
-	if (status == SUCCESS)
-	{
-		found = route_entry_clone(&route);
-		this->routes->put(this->routes, found, found);
-	}
-	this->routes_lock->unlock(this->routes_lock);
-	return status;
-}
-
-METHOD(kernel_net_t, del_route, status_t,
-	private_kernel_pfroute_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
-	host_t *gateway, host_t *src_ip, char *if_name)
-{
-	status_t status;
-	route_entry_t *found, route = {
-		.dst_net = dst_net,
-		.prefixlen = prefixlen,
-		.gateway = gateway,
-		.if_name = if_name,
-	};
-
-	this->routes_lock->lock(this->routes_lock);
-	found = this->routes->get(this->routes, &route);
-	if (!found)
-	{
-		this->routes_lock->unlock(this->routes_lock);
-		return NOT_FOUND;
-	}
-	this->routes->remove(this->routes, found);
-	route_entry_destroy(found);
-	status = manage_route(this, RTM_DELETE, dst_net, prefixlen, gateway,
-						  if_name);
-	this->routes_lock->unlock(this->routes_lock);
-	return status;
-}
-
-/**
- * Do a route lookup for dest and return either the nexthop or the source
- * address.
- */
-static host_t *get_route(private_kernel_pfroute_net_t *this, bool nexthop,
-						 host_t *dest, host_t *src)
-{
-	struct {
-		struct rt_msghdr hdr;
-		char buf[sizeof(struct sockaddr_storage) * RTAX_MAX];
-	} msg = {
-		.hdr = {
-			.rtm_version = RTM_VERSION,
-			.rtm_type = RTM_GET,
-			.rtm_pid = this->pid,
-			.rtm_seq = ref_get(&this->seq),
-		},
-	};
-	host_t *host = NULL;
-	enumerator_t *enumerator;
-	struct sockaddr *addr;
-	bool failed = FALSE;
-	int type;
-
-retry:
-	msg.hdr.rtm_msglen = sizeof(struct rt_msghdr);
-	for (type = 0; type < RTAX_MAX; type++)
-	{
-		switch (type)
-		{
-			case RTAX_DST:
-				add_rt_addr(&msg.hdr, RTA_DST, dest);
-				break;
-			case RTAX_IFA:
-				add_rt_addr(&msg.hdr, RTA_IFA, src);
-				break;
-			case RTAX_IFP:
-				if (!nexthop)
-				{	/* add an empty IFP to ensure we get a source address */
-					add_rt_ifname(&msg.hdr, RTA_IFP, "");
-				}
-				break;
-			default:
-				break;
-		}
-	}
-	this->mutex->lock(this->mutex);
-
-	while (this->waiting_seq)
-	{
-		this->condvar->wait(this->condvar, this->mutex);
-	}
-	this->waiting_seq = msg.hdr.rtm_seq;
-	if (send(this->socket, &msg, msg.hdr.rtm_msglen, 0) == msg.hdr.rtm_msglen)
-	{
-		while (TRUE)
-		{
-			if (this->condvar->timed_wait(this->condvar, this->mutex, 1000))
-			{	/* timed out? */
-				break;
-			}
-			if (!this->reply)
-			{
-				continue;
-			}
-			enumerator = create_rtmsg_enumerator(this->reply);
-			while (enumerator->enumerate(enumerator, &type, &addr))
-			{
-				if (nexthop)
-				{
-					if (type == RTAX_DST && this->reply->rtm_flags & RTF_HOST)
-					{	/* probably a cloned/cached direct route, only use that
-						 * as fallback if no gateway is found */
-						host = host ?: host_create_from_sockaddr(addr);
-					}
-					if (type == RTAX_GATEWAY)
-					{	/* could actually be a MAC address */
-						host_t *gtw = host_create_from_sockaddr(addr);
-						if (gtw)
-						{
-							DESTROY_IF(host);
-							host = gtw;
-						}
-					}
-				}
-				else
-				{
-					if (type == RTAX_IFA)
-					{
-						host = host_create_from_sockaddr(addr);
-					}
-				}
-			}
-			enumerator->destroy(enumerator);
-			break;
-		}
-	}
-	else
-	{
-		failed = TRUE;
-	}
-	free(this->reply);
-	this->reply = NULL;
-	/* signal completion of query to a waiting thread */
-	this->waiting_seq = 0;
-	this->condvar->signal(this->condvar);
-	this->mutex->unlock(this->mutex);
-
-	if (failed)
-	{
-		if (src)
-		{	/* the given source address might be gone, try again without */
-			src = NULL;
-			msg.hdr.rtm_seq = ref_get(&this->seq);
-			msg.hdr.rtm_addrs = 0;
-			memset(msg.buf, 0, sizeof(msg.buf));
-			goto retry;
-		}
-		DBG1(DBG_KNL, "PF_ROUTE lookup failed: %s", strerror(errno));
-	}
-	if (nexthop)
-	{
-		host = host ?: dest->clone(dest);
-	}
-	else
-	{	/* make sure the source address is not virtual and usable */
-		addr_entry_t *entry, lookup = {
-			.ip = host,
-		};
-
-		if (!host)
-		{
-			return NULL;
-		}
-		this->lock->read_lock(this->lock);
-		entry = this->addrs->get_match(this->addrs, &lookup,
-									(void*)addr_map_entry_match_up_and_usable);
-		this->lock->unlock(this->lock);
-		if (!entry)
-		{
-			host->destroy(host);
-			return NULL;
-		}
-	}
-	DBG2(DBG_KNL, "using %H as %s to reach %H", host,
-		 nexthop ? "nexthop" : "address", dest);
-	return host;
-}
-
-METHOD(kernel_net_t, get_source_addr, host_t*,
-	private_kernel_pfroute_net_t *this, host_t *dest, host_t *src)
-{
-	return get_route(this, FALSE, dest, src);
-}
-
-METHOD(kernel_net_t, get_nexthop, host_t*,
-	private_kernel_pfroute_net_t *this, host_t *dest, int prefix, host_t *src)
-{
-	return get_route(this, TRUE, dest, src);
-}
-
-/**
- * Initialize a list of local addresses.
- */
-static status_t init_address_list(private_kernel_pfroute_net_t *this)
-{
-	struct ifaddrs *ifap, *ifa;
-	iface_entry_t *iface, *current;
-	addr_entry_t *addr;
-	enumerator_t *ifaces, *addrs;
-
-	DBG2(DBG_KNL, "known interfaces and IP addresses:");
-
-	if (getifaddrs(&ifap) < 0)
-	{
-		DBG1(DBG_KNL, "  failed to get interfaces!");
-		return FAILED;
-	}
-
-	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
-	{
-		if (ifa->ifa_addr == NULL)
-		{
-			continue;
-		}
-		switch(ifa->ifa_addr->sa_family)
-		{
-			case AF_LINK:
-			case AF_INET:
-			case AF_INET6:
-			{
-				iface = NULL;
-				ifaces = this->ifaces->create_enumerator(this->ifaces);
-				while (ifaces->enumerate(ifaces, &current))
-				{
-					if (streq(current->ifname, ifa->ifa_name))
-					{
-						iface = current;
-						break;
-					}
-				}
-				ifaces->destroy(ifaces);
-
-				if (!iface)
-				{
-					INIT(iface,
-						.ifindex = if_nametoindex(ifa->ifa_name),
-						.flags = ifa->ifa_flags,
-						.addrs = linked_list_create(),
-						.usable = hydra->kernel_interface->is_interface_usable(
-										hydra->kernel_interface, ifa->ifa_name),
-					);
-					memcpy(iface->ifname, ifa->ifa_name, IFNAMSIZ);
-					this->ifaces->insert_last(this->ifaces, iface);
-				}
-
-				if (ifa->ifa_addr->sa_family != AF_LINK)
-				{
-					INIT(addr,
-						.ip = host_create_from_sockaddr(ifa->ifa_addr),
-					);
-					iface->addrs->insert_last(iface->addrs, addr);
-					addr_map_entry_add(this, addr, iface);
-				}
-			}
-		}
-	}
-	freeifaddrs(ifap);
-
-	ifaces = this->ifaces->create_enumerator(this->ifaces);
-	while (ifaces->enumerate(ifaces, &iface))
-	{
-		if (iface->usable && iface->flags & IFF_UP)
-		{
-			DBG2(DBG_KNL, "  %s", iface->ifname);
-			addrs = iface->addrs->create_enumerator(iface->addrs);
-			while (addrs->enumerate(addrs, (void**)&addr))
-			{
-				DBG2(DBG_KNL, "    %H", addr->ip);
-			}
-			addrs->destroy(addrs);
-		}
-	}
-	ifaces->destroy(ifaces);
-
-	return SUCCESS;
-}
-
-METHOD(kernel_net_t, destroy, void,
-	private_kernel_pfroute_net_t *this)
-{
-	enumerator_t *enumerator;
-	route_entry_t *route;
-	addr_entry_t *addr;
-
-	enumerator = this->routes->create_enumerator(this->routes);
-	while (enumerator->enumerate(enumerator, NULL, (void**)&route))
-	{
-		manage_route(this, RTM_DELETE, route->dst_net, route->prefixlen,
-					 route->gateway, route->if_name);
-		route_entry_destroy(route);
-	}
-	enumerator->destroy(enumerator);
-	this->routes->destroy(this->routes);
-	this->routes_lock->destroy(this->routes_lock);
-
-	if (this->socket != -1)
-	{
-		lib->watcher->remove(lib->watcher, this->socket);
-		close(this->socket);
-	}
-
-	net_changes_clear(this);
-	this->net_changes->destroy(this->net_changes);
-	this->net_changes_lock->destroy(this->net_changes_lock);
-
-	enumerator = this->addrs->create_enumerator(this->addrs);
-	while (enumerator->enumerate(enumerator, NULL, (void**)&addr))
-	{
-		free(addr);
-	}
-	enumerator->destroy(enumerator);
-	this->addrs->destroy(this->addrs);
-	this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
-	this->tuns->destroy(this->tuns);
-	this->lock->destroy(this->lock);
-	this->mutex->destroy(this->mutex);
-	this->condvar->destroy(this->condvar);
-	this->roam_lock->destroy(this->roam_lock);
-	free(this->reply);
-	free(this);
-}
-
-/*
- * Described in header.
- */
-kernel_pfroute_net_t *kernel_pfroute_net_create()
-{
-	private_kernel_pfroute_net_t *this;
-
-	INIT(this,
-		.public = {
-			.interface = {
-				.get_features = _get_features,
-				.get_interface = _get_interface_name,
-				.create_address_enumerator = _create_address_enumerator,
-				.get_source_addr = _get_source_addr,
-				.get_nexthop = _get_nexthop,
-				.add_ip = _add_ip,
-				.del_ip = _del_ip,
-				.add_route = _add_route,
-				.del_route = _del_route,
-				.destroy = _destroy,
-			},
-		},
-		.pid = getpid(),
-		.ifaces = linked_list_create(),
-		.addrs = hashtable_create(
-								(hashtable_hash_t)addr_map_entry_hash,
-								(hashtable_equals_t)addr_map_entry_equals, 16),
-		.routes = hashtable_create((hashtable_hash_t)route_entry_hash,
-								   (hashtable_equals_t)route_entry_equals, 16),
-		.net_changes = hashtable_create(
-								   (hashtable_hash_t)net_change_hash,
-								   (hashtable_equals_t)net_change_equals, 16),
-		.tuns = linked_list_create(),
-		.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
-		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
-		.condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
-		.routes_lock = mutex_create(MUTEX_TYPE_DEFAULT),
-		.net_changes_lock = mutex_create(MUTEX_TYPE_DEFAULT),
-		.roam_lock = spinlock_create(),
-		.vip_wait = lib->settings->get_int(lib->settings,
-						"%s.plugins.kernel-pfroute.vip_wait", 1000, lib->ns),
-		.install_virtual_ip = lib->settings->get_bool(lib->settings,
-						"%s.install_virtual_ip", TRUE, lib->ns),
-	);
-	timerclear(&this->last_route_reinstall);
-	timerclear(&this->next_roam);
-
-	/* create a PF_ROUTE socket to communicate with the kernel */
-	this->socket = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
-	if (this->socket == -1)
-	{
-		DBG1(DBG_KNL, "unable to create PF_ROUTE socket");
-		destroy(this);
-		return NULL;
-	}
-
-	if (streq(lib->ns, "starter"))
-	{
-		/* starter has no threads, so we do not register for kernel events */
-		if (shutdown(this->socket, SHUT_RD) != 0)
-		{
-			DBG1(DBG_KNL, "closing read end of PF_ROUTE socket failed: %s",
-				 strerror(errno));
-		}
-	}
-	else
-	{
-		lib->watcher->add(lib->watcher, this->socket, WATCHER_READ,
-						  (watcher_cb_t)receive_events, this);
-	}
-	if (init_address_list(this) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to get interface list");
-		destroy(this);
-		return NULL;
-	}
-
-	return &this->public;
-}
diff --git a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_plugin.c b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_plugin.c
deleted file mode 100644
index 09068b3..0000000
--- a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_plugin.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-
-#include "kernel_pfroute_plugin.h"
-
-#include "kernel_pfroute_net.h"
-
-#include <hydra.h>
-
-typedef struct private_kernel_pfroute_plugin_t private_kernel_pfroute_plugin_t;
-
-/**
- * private data of kernel PF_ROUTE plugin
- */
-struct private_kernel_pfroute_plugin_t {
-	/**
-	 * implements plugin interface
-	 */
-	kernel_pfroute_plugin_t public;
-};
-
-METHOD(plugin_t, get_name, char*,
-	private_kernel_pfroute_plugin_t *this)
-{
-	return "kernel-pfroute";
-}
-
-METHOD(plugin_t, get_features, int,
-	private_kernel_pfroute_plugin_t *this, plugin_feature_t *features[])
-{
-	static plugin_feature_t f[] = {
-		PLUGIN_CALLBACK(kernel_net_register, kernel_pfroute_net_create),
-			PLUGIN_PROVIDE(CUSTOM, "kernel-net"),
-	};
-	*features = f;
-	return countof(f);
-}
-
-METHOD(plugin_t, destroy, void,
-	private_kernel_pfroute_plugin_t *this)
-{
-	free(this);
-}
-
-/*
- * see header file
- */
-plugin_t *kernel_pfroute_plugin_create()
-{
-	private_kernel_pfroute_plugin_t *this;
-
-	INIT(this,
-		.public = {
-			.plugin = {
-				.get_name = _get_name,
-				.get_features = _get_features,
-				.destroy = _destroy,
-			},
-		},
-	);
-
-	return &this->public.plugin;
-}
diff --git a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_plugin.h b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_plugin.h
deleted file mode 100644
index b8ee31a..0000000
--- a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_plugin.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-/**
- * @defgroup kernel_pfroute kernel_pfroute
- * @ingroup hplugins
- *
- * @defgroup kernel_pfroute_plugin kernel_pfroute_plugin
- * @{ @ingroup kernel_pfroute
- */
-
-#ifndef KERNEL_PFROUTE_PLUGIN_H_
-#define KERNEL_PFROUTE_PLUGIN_H_
-
-#include <plugins/plugin.h>
-
-typedef struct kernel_pfroute_plugin_t kernel_pfroute_plugin_t;
-
-/**
- * PF_ROUTE kernel interface plugin
- */
-struct kernel_pfroute_plugin_t {
-
-	/**
-	 * implements plugin interface
-	 */
-	plugin_t plugin;
-};
-
-#endif /** KERNEL_PFROUTE_PLUGIN_H_ @}*/
diff --git a/src/libhydra/tests/Makefile.am b/src/libhydra/tests/Makefile.am
deleted file mode 100644
index 5acd5c2..0000000
--- a/src/libhydra/tests/Makefile.am
+++ /dev/null
@@ -1,18 +0,0 @@
-TESTS = hydra_tests
-
-check_PROGRAMS = $(TESTS)
-
-hydra_tests_SOURCES = \
-  hydra_tests.h hydra_tests.c
-
-hydra_tests_CFLAGS = \
-  -I$(top_srcdir)/src/libhydra \
-  -I$(top_srcdir)/src/libstrongswan \
-  -I$(top_srcdir)/src/libstrongswan/tests \
-  @COVERAGE_CFLAGS@
-
-hydra_tests_LDFLAGS = @COVERAGE_LDFLAGS@
-hydra_tests_LDADD = \
-  $(top_builddir)/src/libhydra/libhydra.la \
-  $(top_builddir)/src/libstrongswan/libstrongswan.la \
-  $(top_builddir)/src/libstrongswan/tests/libtest.la
diff --git a/src/libhydra/tests/Makefile.in b/src/libhydra/tests/Makefile.in
deleted file mode 100644
index 1fa889d..0000000
--- a/src/libhydra/tests/Makefile.in
+++ /dev/null
@@ -1,839 +0,0 @@
-# Makefile.in generated by automake 1.14.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 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.
-
- at SET_MAKE@
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
-  case $${target_option-} in \
-      ?) ;; \
-      *) echo "am__make_running_with_option: internal error: invalid" \
-              "target option '$${target_option-}' specified" >&2; \
-         exit 1;; \
-  esac; \
-  has_opt=no; \
-  sane_makeflags=$$MAKEFLAGS; \
-  if $(am__is_gnu_make); then \
-    sane_makeflags=$$MFLAGS; \
-  else \
-    case $$MAKEFLAGS in \
-      *\\[\ \	]*) \
-        bs=\\; \
-        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
-          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
-    esac; \
-  fi; \
-  skip_next=no; \
-  strip_trailopt () \
-  { \
-    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
-  }; \
-  for flg in $$sane_makeflags; do \
-    test $$skip_next = yes && { skip_next=no; continue; }; \
-    case $$flg in \
-      *=*|--*) continue;; \
-        -*I) strip_trailopt 'I'; skip_next=yes;; \
-      -*I?*) strip_trailopt 'I';; \
-        -*O) strip_trailopt 'O'; skip_next=yes;; \
-      -*O?*) strip_trailopt 'O';; \
-        -*l) strip_trailopt 'l'; skip_next=yes;; \
-      -*l?*) strip_trailopt 'l';; \
-      -[dEDm]) skip_next=yes;; \
-      -[JT]) skip_next=yes;; \
-    esac; \
-    case $$flg in \
-      *$$target_option*) has_opt=yes; break;; \
-    esac; \
-  done; \
-  test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@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@
-TESTS = hydra_tests$(EXEEXT)
-check_PROGRAMS = $(am__EXEEXT_1)
-subdir = src/libhydra/tests
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
-	$(top_srcdir)/depcomp
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
-	$(top_srcdir)/m4/config/ltoptions.m4 \
-	$(top_srcdir)/m4/config/ltsugar.m4 \
-	$(top_srcdir)/m4/config/ltversion.m4 \
-	$(top_srcdir)/m4/config/lt~obsolete.m4 \
-	$(top_srcdir)/m4/macros/split-package-version.m4 \
-	$(top_srcdir)/m4/macros/with.m4 \
-	$(top_srcdir)/m4/macros/enable-disable.m4 \
-	$(top_srcdir)/m4/macros/add-plugin.m4 \
-	$(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-	$(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-am__EXEEXT_1 = hydra_tests$(EXEEXT)
-am_hydra_tests_OBJECTS = hydra_tests-hydra_tests.$(OBJEXT)
-hydra_tests_OBJECTS = $(am_hydra_tests_OBJECTS)
-hydra_tests_DEPENDENCIES = $(top_builddir)/src/libhydra/libhydra.la \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libstrongswan/tests/libtest.la
-AM_V_lt = $(am__v_lt_ at AM_V@)
-am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 = 
-hydra_tests_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(hydra_tests_CFLAGS) \
-	$(CFLAGS) $(hydra_tests_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_P = $(am__v_P_ at AM_V@)
-am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_ at AM_V@)
-am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 = 
-AM_V_at = $(am__v_at_ at AM_V@)
-am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 = 
-DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-	$(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_ at AM_V@)
-am__v_CC_ = $(am__v_CC_ at AM_DEFAULT_V@)
-am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 = 
-CCLD = $(CC)
-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-	$(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_ at AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_ at AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo "  CCLD    " $@;
-am__v_CCLD_1 = 
-SOURCES = $(hydra_tests_SOURCES)
-DIST_SOURCES = $(hydra_tests_SOURCES)
-am__can_run_installinfo = \
-  case $$AM_UPDATE_INFO_DIR in \
-    n|no|NO) false;; \
-    *) (install-info --version) >/dev/null 2>&1;; \
-  esac
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates.  Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
-  BEGIN { nonempty = 0; } \
-  { items[$$0] = 1; nonempty = 1; } \
-  END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique.  This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
-  list='$(am__tagged_files)'; \
-  unique=`for i in $$list; do \
-    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-  done | $(am__uniquify_input)`
-ETAGS = etags
-CTAGS = ctags
-am__tty_colors_dummy = \
-  mgn= red= grn= lgn= blu= brg= std=; \
-  am__color_tests=no
-am__tty_colors = { \
-  $(am__tty_colors_dummy); \
-  if test "X$(AM_COLOR_TESTS)" = Xno; then \
-    am__color_tests=no; \
-  elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
-    am__color_tests=yes; \
-  elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
-    am__color_tests=yes; \
-  fi; \
-  if test $$am__color_tests = yes; then \
-    red=''; \
-    grn=''; \
-    lgn=''; \
-    blu=''; \
-    mgn=''; \
-    brg=''; \
-    std=''; \
-  fi; \
-}
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-ALLOCA = @ALLOCA@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BFDLIB = @BFDLIB@
-BTLIB = @BTLIB@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
-COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLIB = @DLLIB@
-DLLTOOL = @DLLTOOL@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-EASY_INSTALL = @EASY_INSTALL@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FGREP = @FGREP@
-GEM = @GEM@
-GENHTML = @GENHTML@
-GPERF = @GPERF@
-GPRBUILD = @GPRBUILD@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LCOV = @LCOV@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LEX = @LEX@
-LEXLIB = @LEXLIB@
-LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-MYSQLCFLAG = @MYSQLCFLAG@
-MYSQLCONFIG = @MYSQLCONFIG@
-MYSQLLIB = @MYSQLLIB@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OPENSSL_LIB = @OPENSSL_LIB@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
-PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
-PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
-PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PERL = @PERL@
-PKG_CONFIG = @PKG_CONFIG@
-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
-PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
-PTHREADLIB = @PTHREADLIB@
-PYTHON = @PYTHON@
-PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
-PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
-PYTHON_PLATFORM = @PYTHON_PLATFORM@
-PYTHON_PREFIX = @PYTHON_PREFIX@
-PYTHON_VERSION = @PYTHON_VERSION@
-PY_TEST = @PY_TEST@
-RANLIB = @RANLIB@
-RTLIB = @RTLIB@
-RUBY = @RUBY@
-RUBYGEMDIR = @RUBYGEMDIR@
-RUBYINCLUDE = @RUBYINCLUDE@
-RUBYLIB = @RUBYLIB@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-SOCKLIB = @SOCKLIB@
-STRIP = @STRIP@
-UNWINDLIB = @UNWINDLIB@
-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_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-aikgen_plugins = @aikgen_plugins@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-attest_plugins = @attest_plugins@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-c_plugins = @c_plugins@
-charon_natt_port = @charon_natt_port@
-charon_plugins = @charon_plugins@
-charon_udp_port = @charon_udp_port@
-clearsilver_LIBS = @clearsilver_LIBS@
-cmd_plugins = @cmd_plugins@
-datadir = @datadir@
-datarootdir = @datarootdir@
-dbusservicedir = @dbusservicedir@
-dev_headers = @dev_headers@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-fips_mode = @fips_mode@
-gtk_CFLAGS = @gtk_CFLAGS@
-gtk_LIBS = @gtk_LIBS@
-h_plugins = @h_plugins@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-imcvdir = @imcvdir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-ipsec_script = @ipsec_script@
-ipsec_script_upper = @ipsec_script_upper@
-ipsecdir = @ipsecdir@
-ipsecgroup = @ipsecgroup@
-ipseclibdir = @ipseclibdir@
-ipsecuser = @ipsecuser@
-json_CFLAGS = @json_CFLAGS@
-json_LIBS = @json_LIBS@
-libdir = @libdir@
-libexecdir = @libexecdir@
-libiptc_CFLAGS = @libiptc_CFLAGS@
-libiptc_LIBS = @libiptc_LIBS@
-linux_headers = @linux_headers@
-localedir = @localedir@
-localstatedir = @localstatedir@
-maemo_CFLAGS = @maemo_CFLAGS@
-maemo_LIBS = @maemo_LIBS@
-manager_plugins = @manager_plugins@
-mandir = @mandir@
-medsrv_plugins = @medsrv_plugins@
-mkdir_p = @mkdir_p@
-nm_CFLAGS = @nm_CFLAGS@
-nm_LIBS = @nm_LIBS@
-nm_ca_dir = @nm_ca_dir@
-nm_plugins = @nm_plugins@
-oldincludedir = @oldincludedir@
-pcsclite_CFLAGS = @pcsclite_CFLAGS@
-pcsclite_LIBS = @pcsclite_LIBS@
-pdfdir = @pdfdir@
-piddir = @piddir@
-pkgpyexecdir = @pkgpyexecdir@
-pkgpythondir = @pkgpythondir@
-pki_plugins = @pki_plugins@
-plugindir = @plugindir@
-pool_plugins = @pool_plugins@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-pyexecdir = @pyexecdir@
-pythondir = @pythondir@
-random_device = @random_device@
-resolv_conf = @resolv_conf@
-routing_table = @routing_table@
-routing_table_prio = @routing_table_prio@
-s_plugins = @s_plugins@
-sbindir = @sbindir@
-scepclient_plugins = @scepclient_plugins@
-scripts_plugins = @scripts_plugins@
-sharedstatedir = @sharedstatedir@
-soup_CFLAGS = @soup_CFLAGS@
-soup_LIBS = @soup_LIBS@
-srcdir = @srcdir@
-starter_plugins = @starter_plugins@
-strongswan_conf = @strongswan_conf@
-strongswan_options = @strongswan_options@
-swanctldir = @swanctldir@
-sysconfdir = @sysconfdir@
-systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
-systemd_daemon_LIBS = @systemd_daemon_LIBS@
-systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
-systemd_journal_LIBS = @systemd_journal_LIBS@
-systemdsystemunitdir = @systemdsystemunitdir@
-t_plugins = @t_plugins@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-urandom_device = @urandom_device@
-xml_CFLAGS = @xml_CFLAGS@
-xml_LIBS = @xml_LIBS@
-hydra_tests_SOURCES = \
-  hydra_tests.h hydra_tests.c
-
-hydra_tests_CFLAGS = \
-  -I$(top_srcdir)/src/libhydra \
-  -I$(top_srcdir)/src/libstrongswan \
-  -I$(top_srcdir)/src/libstrongswan/tests \
-  @COVERAGE_CFLAGS@
-
-hydra_tests_LDFLAGS = @COVERAGE_LDFLAGS@
-hydra_tests_LDADD = \
-  $(top_builddir)/src/libhydra/libhydra.la \
-  $(top_builddir)/src/libstrongswan/libstrongswan.la \
-  $(top_builddir)/src/libstrongswan/tests/libtest.la
-
-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 ) \
-	        && { if test -f $@; then exit 0; else break; fi; }; \
-	      exit 1;; \
-	  esac; \
-	done; \
-	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libhydra/tests/Makefile'; \
-	$(am__cd) $(top_srcdir) && \
-	  $(AUTOMAKE) --gnu src/libhydra/tests/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
-$(am__aclocal_m4_deps):
-
-clean-checkPROGRAMS:
-	@list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
-	echo " rm -f" $$list; \
-	rm -f $$list || exit $$?; \
-	test -n "$(EXEEXT)" || exit 0; \
-	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
-	echo " rm -f" $$list; \
-	rm -f $$list
-
-hydra_tests$(EXEEXT): $(hydra_tests_OBJECTS) $(hydra_tests_DEPENDENCIES) $(EXTRA_hydra_tests_DEPENDENCIES) 
-	@rm -f hydra_tests$(EXEEXT)
-	$(AM_V_CCLD)$(hydra_tests_LINK) $(hydra_tests_OBJECTS) $(hydra_tests_LDADD) $(LIBS)
-
-mostlyclean-compile:
-	-rm -f *.$(OBJEXT)
-
-distclean-compile:
-	-rm -f *.tab.c
-
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/hydra_tests-hydra_tests.Po at am__quote@
-
-.c.o:
- at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
- at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
- at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ $<
-
-.c.obj:
- at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
- at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
- at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-
-.c.lo:
- at am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
- at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
- at am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LTCOMPILE) -c -o $@ $<
-
-hydra_tests-hydra_tests.o: hydra_tests.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hydra_tests_CFLAGS) $(CFLAGS) -MT hydra_tests-hydra_tests.o -MD -MP -MF $(DEPDIR)/hydra_tests-hydra_tests.Tpo -c -o hydra_tests-hydra_tests.o `test -f 'hydra_tests.c' || echo '$(srcdir)/'`hydra_tests.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/hydra_tests-hydra_tests.Tpo $(DEPDIR)/hydra_tests-hydra_tests.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='hydra_tests.c' object='hydra_tests-hydra_tests.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hydra_tests_CFLAGS) $(CFLAGS) -c -o hydra_tests-hydra_tests.o `test -f 'hydra_tests.c' || echo '$(srcdir)/'`hydra_tests.c
-
-hydra_tests-hydra_tests.obj: hydra_tests.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hydra_tests_CFLAGS) $(CFLAGS) -MT hydra_tests-hydra_tests.obj -MD -MP -MF $(DEPDIR)/hydra_tests-hydra_tests.Tpo -c -o hydra_tests-hydra_tests.obj `if test -f 'hydra_tests.c'; then $(CYGPATH_W) 'hydra_tests.c'; else $(CYGPATH_W) '$(srcdir)/hydra_tests.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/hydra_tests-hydra_tests.Tpo $(DEPDIR)/hydra_tests-hydra_tests.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='hydra_tests.c' object='hydra_tests-hydra_tests.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hydra_tests_CFLAGS) $(CFLAGS) -c -o hydra_tests-hydra_tests.obj `if test -f 'hydra_tests.c'; then $(CYGPATH_W) 'hydra_tests.c'; else $(CYGPATH_W) '$(srcdir)/hydra_tests.c'; fi`
-
-mostlyclean-libtool:
-	-rm -f *.lo
-
-clean-libtool:
-	-rm -rf .libs _libs
-
-ID: $(am__tagged_files)
-	$(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-am
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-	set x; \
-	here=`pwd`; \
-	$(am__define_uniq_tagged_files); \
-	shift; \
-	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-	  test -n "$$unique" || unique=$$empty_fix; \
-	  if test $$# -gt 0; then \
-	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-	      "$$@" $$unique; \
-	  else \
-	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-	      $$unique; \
-	  fi; \
-	fi
-ctags: ctags-am
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-	$(am__define_uniq_tagged_files); \
-	test -z "$(CTAGS_ARGS)$$unique" \
-	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-	     $$unique
-
-GTAGS:
-	here=`$(am__cd) $(top_builddir) && pwd` \
-	  && $(am__cd) $(top_srcdir) \
-	  && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-am
-
-cscopelist-am: $(am__tagged_files)
-	list='$(am__tagged_files)'; \
-	case "$(srcdir)" in \
-	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
-	  *) sdir=$(subdir)/$(srcdir) ;; \
-	esac; \
-	for i in $$list; do \
-	  if test -f "$$i"; then \
-	    echo "$(subdir)/$$i"; \
-	  else \
-	    echo "$$sdir/$$i"; \
-	  fi; \
-	done >> $(top_builddir)/cscope.files
-
-distclean-tags:
-	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-check-TESTS: $(TESTS)
-	@failed=0; all=0; xfail=0; xpass=0; skip=0; \
-	srcdir=$(srcdir); export srcdir; \
-	list=' $(TESTS) '; \
-	$(am__tty_colors); \
-	if test -n "$$list"; then \
-	  for tst in $$list; do \
-	    if test -f ./$$tst; then dir=./; \
-	    elif test -f $$tst; then dir=; \
-	    else dir="$(srcdir)/"; fi; \
-	    if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
-	      all=`expr $$all + 1`; \
-	      case " $(XFAIL_TESTS) " in \
-	      *[\ \	]$$tst[\ \	]*) \
-		xpass=`expr $$xpass + 1`; \
-		failed=`expr $$failed + 1`; \
-		col=$$red; res=XPASS; \
-	      ;; \
-	      *) \
-		col=$$grn; res=PASS; \
-	      ;; \
-	      esac; \
-	    elif test $$? -ne 77; then \
-	      all=`expr $$all + 1`; \
-	      case " $(XFAIL_TESTS) " in \
-	      *[\ \	]$$tst[\ \	]*) \
-		xfail=`expr $$xfail + 1`; \
-		col=$$lgn; res=XFAIL; \
-	      ;; \
-	      *) \
-		failed=`expr $$failed + 1`; \
-		col=$$red; res=FAIL; \
-	      ;; \
-	      esac; \
-	    else \
-	      skip=`expr $$skip + 1`; \
-	      col=$$blu; res=SKIP; \
-	    fi; \
-	    echo "$${col}$$res$${std}: $$tst"; \
-	  done; \
-	  if test "$$all" -eq 1; then \
-	    tests="test"; \
-	    All=""; \
-	  else \
-	    tests="tests"; \
-	    All="All "; \
-	  fi; \
-	  if test "$$failed" -eq 0; then \
-	    if test "$$xfail" -eq 0; then \
-	      banner="$$All$$all $$tests passed"; \
-	    else \
-	      if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
-	      banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
-	    fi; \
-	  else \
-	    if test "$$xpass" -eq 0; then \
-	      banner="$$failed of $$all $$tests failed"; \
-	    else \
-	      if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
-	      banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
-	    fi; \
-	  fi; \
-	  dashes="$$banner"; \
-	  skipped=""; \
-	  if test "$$skip" -ne 0; then \
-	    if test "$$skip" -eq 1; then \
-	      skipped="($$skip test was not run)"; \
-	    else \
-	      skipped="($$skip tests were not run)"; \
-	    fi; \
-	    test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
-	      dashes="$$skipped"; \
-	  fi; \
-	  report=""; \
-	  if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
-	    report="Please report to $(PACKAGE_BUGREPORT)"; \
-	    test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
-	      dashes="$$report"; \
-	  fi; \
-	  dashes=`echo "$$dashes" | sed s/./=/g`; \
-	  if test "$$failed" -eq 0; then \
-	    col="$$grn"; \
-	  else \
-	    col="$$red"; \
-	  fi; \
-	  echo "$${col}$$dashes$${std}"; \
-	  echo "$${col}$$banner$${std}"; \
-	  test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
-	  test -z "$$report" || echo "$${col}$$report$${std}"; \
-	  echo "$${col}$$dashes$${std}"; \
-	  test "$$failed" -eq 0; \
-	else :; fi
-
-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 "$(distdir)/$$file"; then \
-	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-	    fi; \
-	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-	    fi; \
-	    cp -fpR $$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
-	$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
-	$(MAKE) $(AM_MAKEFLAGS) check-TESTS
-check: check-am
-all-am: Makefile
-installdirs:
-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:
-	if test -z '$(STRIP)'; then \
-	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-	      install; \
-	else \
-	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-	fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
-	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-checkPROGRAMS clean-generic clean-libtool \
-	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
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am:
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-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:
-
-.MAKE: check-am install-am install-strip
-
-.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \
-	clean-checkPROGRAMS clean-generic clean-libtool cscopelist-am \
-	ctags ctags-am 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-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 tags-am uninstall uninstall-am
-
-
-# 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/libhydra/tests/hydra_tests.c b/src/libhydra/tests/hydra_tests.c
deleted file mode 100644
index 0d6387b..0000000
--- a/src/libhydra/tests/hydra_tests.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#include <test_runner.h>
-#include <hydra.h>
-
-/* declare test suite constructors */
-#define TEST_SUITE(x) test_suite_t* x();
-#define TEST_SUITE_DEPEND(x, ...) TEST_SUITE(x)
-#include "hydra_tests.h"
-#undef TEST_SUITE
-#undef TEST_SUITE_DEPEND
-
-static test_configuration_t tests[] = {
-#define TEST_SUITE(x) \
-	{ .suite = x, },
-#define TEST_SUITE_DEPEND(x, type, ...) \
-	{ .suite = x, .feature = PLUGIN_DEPENDS(type, __VA_ARGS__) },
-#include "hydra_tests.h"
-	{ .suite = NULL, }
-};
-
-static bool test_runner_init(bool init)
-{
-	if (init)
-	{
-		libhydra_init();
-	}
-	else
-	{
-		lib->processor->set_threads(lib->processor, 0);
-		lib->processor->cancel(lib->processor);
-		libhydra_deinit();
-	}
-	return TRUE;
-}
-
-int main(int argc, char *argv[])
-{
-	return test_runner_run("libhydra", tests, test_runner_init);
-}
diff --git a/src/libhydra/tests/hydra_tests.h b/src/libhydra/tests/hydra_tests.h
deleted file mode 100644
index 6b213d0..0000000
--- a/src/libhydra/tests/hydra_tests.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
diff --git a/src/libimcv/Makefile.in b/src/libimcv/Makefile.in
index ed2934c..200f959 100644
--- a/src/libimcv/Makefile.in
+++ b/src/libimcv/Makefile.in
@@ -586,6 +586,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libimcv/imc/imc_os_info.c b/src/libimcv/imc/imc_os_info.c
index 0a094eb..55e152a 100644
--- a/src/libimcv/imc/imc_os_info.c
+++ b/src/libimcv/imc/imc_os_info.c
@@ -383,6 +383,7 @@ static bool extract_platform_info(os_type_t *type, chunk_t *name,
 	FILE *file;
 	u_char buf[BUF_LEN], *pos = buf;
 	int len = BUF_LEN - 1;
+	long file_len;
 	os_type_t os_type = OS_TYPE_UNKNOWN;
 	chunk_t os_name = chunk_empty;
 	chunk_t os_version = chunk_empty;
@@ -425,15 +426,22 @@ static bool extract_platform_info(os_type_t *type, chunk_t *name,
 
 		/* read release file into buffer */
 		fseek(file, 0, SEEK_END);
-		len = min(ftell(file), len);
+		file_len = ftell(file);
+		if (file_len < 0)
+		{
+			DBG1(DBG_IMC, "failed to determine size of \"%s\"", releases[i]);
+			fclose(file);
+			return FALSE;
+		}
+		len = min(file_len, len);
 		rewind(file);
-		buf[len] = '\0';
 		if (fread(buf, 1, len, file) != len)
 		{
 			DBG1(DBG_IMC, "failed to read file \"%s\"", releases[i]);
 			fclose(file);
 			return FALSE;
 		}
+		buf[len] = '\0';
 		fclose(file);
 
 		DBG1(DBG_IMC, "processing \"%s\" file", releases[i]);
diff --git a/src/libimcv/plugins/imc_attestation/Makefile.in b/src/libimcv/plugins/imc_attestation/Makefile.in
index 8ad5618..6d9533d 100644
--- a/src/libimcv/plugins/imc_attestation/Makefile.in
+++ b/src/libimcv/plugins/imc_attestation/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libimcv/plugins/imc_hcd/Makefile.in b/src/libimcv/plugins/imc_hcd/Makefile.in
index da7523c..0d603c9 100644
--- a/src/libimcv/plugins/imc_hcd/Makefile.in
+++ b/src/libimcv/plugins/imc_hcd/Makefile.in
@@ -411,6 +411,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libimcv/plugins/imc_os/Makefile.in b/src/libimcv/plugins/imc_os/Makefile.in
index 3b75386..d1787da 100644
--- a/src/libimcv/plugins/imc_os/Makefile.in
+++ b/src/libimcv/plugins/imc_os/Makefile.in
@@ -411,6 +411,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libimcv/plugins/imc_scanner/Makefile.in b/src/libimcv/plugins/imc_scanner/Makefile.in
index 7b69689..2f03a7c 100644
--- a/src/libimcv/plugins/imc_scanner/Makefile.in
+++ b/src/libimcv/plugins/imc_scanner/Makefile.in
@@ -412,6 +412,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libimcv/plugins/imc_swid/Makefile.in b/src/libimcv/plugins/imc_swid/Makefile.in
index 2847f09..981f864 100644
--- a/src/libimcv/plugins/imc_swid/Makefile.in
+++ b/src/libimcv/plugins/imc_swid/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libimcv/plugins/imc_test/Makefile.in b/src/libimcv/plugins/imc_test/Makefile.in
index 2048caa..7bf4590 100644
--- a/src/libimcv/plugins/imc_test/Makefile.in
+++ b/src/libimcv/plugins/imc_test/Makefile.in
@@ -411,6 +411,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libimcv/plugins/imv_attestation/Makefile.in b/src/libimcv/plugins/imv_attestation/Makefile.in
index 09a0ab0..d3f7900 100644
--- a/src/libimcv/plugins/imv_attestation/Makefile.in
+++ b/src/libimcv/plugins/imv_attestation/Makefile.in
@@ -423,6 +423,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation_agent.c b/src/libimcv/plugins/imv_attestation/imv_attestation_agent.c
index 28ebd00..91c12f3 100644
--- a/src/libimcv/plugins/imv_attestation/imv_attestation_agent.c
+++ b/src/libimcv/plugins/imv_attestation/imv_attestation_agent.c
@@ -603,8 +603,8 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 							if (!comp)
 							{
 								comp_name->log(comp_name, "unregistered ");
-								comp_name->destroy(comp_name);
 							}
+							comp_name->destroy(comp_name);
 						}
 
 						/* do TPM IMA measurements */
@@ -620,8 +620,8 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 							if (!comp)
 							{
 								comp_name->log(comp_name, "unregistered ");
-								comp_name->destroy(comp_name);
 							}
+							comp_name->destroy(comp_name);
 						}
 
 						/* do TPM TRUSTED BOOT measurements */
@@ -637,8 +637,8 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 							if (!comp)
 							{
 								comp_name->log(comp_name, "unregistered ");
-								comp_name->destroy(comp_name);
 							}
+							comp_name->destroy(comp_name);
 						}
 						attestation_state->set_handshake_state(attestation_state,
 											IMV_ATTESTATION_STATE_NONCE_REQ);
diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation_state.h b/src/libimcv/plugins/imv_attestation/imv_attestation_state.h
index 39a8eee..d9bb47c 100644
--- a/src/libimcv/plugins/imv_attestation/imv_attestation_state.h
+++ b/src/libimcv/plugins/imv_attestation/imv_attestation_state.h
@@ -115,7 +115,7 @@ struct imv_attestation_state_t {
 	/**
 	 * Create and add an entry to the list of Functional Components
 	 *
-	 * @param name				Component Functional Name
+	 * @param name				Component Functional Name (cloned)
 	 * @param depth				Sub-component Depth
 	 * @param pts_db			PTS measurement database
 	 * @return					created functional component instance or NULL
diff --git a/src/libimcv/plugins/imv_hcd/Makefile.in b/src/libimcv/plugins/imv_hcd/Makefile.in
index ea01764..c179a94 100644
--- a/src/libimcv/plugins/imv_hcd/Makefile.in
+++ b/src/libimcv/plugins/imv_hcd/Makefile.in
@@ -411,6 +411,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libimcv/plugins/imv_os/Makefile.in b/src/libimcv/plugins/imv_os/Makefile.in
index ec34889..c6f925a 100644
--- a/src/libimcv/plugins/imv_os/Makefile.in
+++ b/src/libimcv/plugins/imv_os/Makefile.in
@@ -419,6 +419,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libimcv/plugins/imv_scanner/Makefile.in b/src/libimcv/plugins/imv_scanner/Makefile.in
index 08abbf5..0eee4d1 100644
--- a/src/libimcv/plugins/imv_scanner/Makefile.in
+++ b/src/libimcv/plugins/imv_scanner/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libimcv/plugins/imv_swid/Makefile.in b/src/libimcv/plugins/imv_swid/Makefile.in
index 936bee8..ce246da 100644
--- a/src/libimcv/plugins/imv_swid/Makefile.in
+++ b/src/libimcv/plugins/imv_swid/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libimcv/plugins/imv_swid/imv_swid_agent.c b/src/libimcv/plugins/imv_swid/imv_swid_agent.c
index 6d32783..c057e7e 100644
--- a/src/libimcv/plugins/imv_swid/imv_swid_agent.c
+++ b/src/libimcv/plugins/imv_swid/imv_swid_agent.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2015 Andreas Steffen
+ * Copyright (C) 2013-2016 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -213,7 +213,8 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
 				if (request_id == swid_state->get_request_id(swid_state))
 				{
 					swid_state->set_swid_inventory(swid_state, inventory);
-					swid_state->set_count(swid_state, tag_id_count, 0);
+					swid_state->set_count(swid_state, tag_id_count, 0,
+										  in_msg->get_src_id(in_msg));
 				}
 				else
 				{
@@ -251,7 +252,8 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
 
 				if (request_id == swid_state->get_request_id(swid_state))
 				{
-					swid_state->set_count(swid_state, 0, tag_count);
+					swid_state->set_count(swid_state, 0, tag_count,
+										  in_msg->get_src_id(in_msg));
 
 					if (this->rest_api)
 					{
@@ -387,7 +389,8 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 	}
 
 	/* Create an empty out message - we might need it */
-	out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
+	out_msg = imv_msg_create(this->agent, state, id, imv_id,
+							 swid_state->get_imc_id(swid_state),
 							 msg_types[0]);
 
 	if (!imcv_db)
diff --git a/src/libimcv/plugins/imv_swid/imv_swid_state.c b/src/libimcv/plugins/imv_swid/imv_swid_state.c
index 04364b0..fb9493a 100644
--- a/src/libimcv/plugins/imv_swid/imv_swid_state.c
+++ b/src/libimcv/plugins/imv_swid/imv_swid_state.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2014 Andreas Steffen
+ * Copyright (C) 2013-2016 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -123,6 +123,11 @@ struct private_imv_swid_state_t {
 	uint32_t missing;
 
 	/**
+	 * SWID IMC ID
+	 */
+	TNC_UInt32 imc_id;
+
+	/**
 	 * Top level JSON object
 	 */
 	json_object *jobj;
@@ -326,10 +331,12 @@ METHOD(imv_swid_state_t, get_missing, uint32_t,
 }
 
 METHOD(imv_swid_state_t, set_count, void,
-	private_imv_swid_state_t *this, int tag_id_count, int tag_count)
+	private_imv_swid_state_t *this, int tag_id_count, int tag_count,
+	TNC_UInt32 imc_id)
 {
 	this->tag_id_count += tag_id_count;
 	this->tag_count += tag_count;
+	this->imc_id = imc_id;
 }
 
 METHOD(imv_swid_state_t, get_count, void,
@@ -345,6 +352,12 @@ METHOD(imv_swid_state_t, get_count, void,
 	}
 }
 
+METHOD(imv_swid_state_t, get_imc_id, TNC_UInt32,
+	private_imv_swid_state_t *this)
+{
+	return this->imc_id;
+}
+
 /**
  * Described in header.
  */
@@ -384,12 +397,14 @@ imv_state_t *imv_swid_state_create(TNC_ConnectionID connection_id)
 			.get_missing = _get_missing,
 			.set_count = _set_count,
 			.get_count = _get_count,
+			.get_imc_id = _get_imc_id,
 		},
 		.state = TNC_CONNECTION_STATE_CREATE,
 		.rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
 		.eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
 		.connection_id = connection_id,
 		.contracts = seg_contract_manager_create(),
+		.imc_id = TNC_IMCID_ANY,
 		.jobj = json_object_new_object(),
 		.jarray = json_object_new_array(),
 	);
diff --git a/src/libimcv/plugins/imv_swid/imv_swid_state.h b/src/libimcv/plugins/imv_swid/imv_swid_state.h
index af5d95c..5fe99ec 100644
--- a/src/libimcv/plugins/imv_swid/imv_swid_state.h
+++ b/src/libimcv/plugins/imv_swid/imv_swid_state.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2014 Andreas Steffen
+ * Copyright (C) 2013-2016 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -81,19 +81,19 @@ struct imv_swid_state_t {
 	 */
 	uint32_t (*get_request_id)(imv_swid_state_t *this);
 
-    /**
-     * Set or extend the SWID Tag ID inventory in the state
-     *
-     * @param inventory			SWID Tags ID inventory to be added
-     */
-    void (*set_swid_inventory)(imv_swid_state_t *this, swid_inventory_t *inventory);
+	/**
+	 * Set or extend the SWID Tag ID inventory in the state
+	 *
+	 * @param inventory			SWID Tags ID inventory to be added
+	 */
+	void (*set_swid_inventory)(imv_swid_state_t *this, swid_inventory_t *inventory);
 
-   /**
-     * Get the encoding of the complete SWID Tag ID inventory
-     *
-     * @return			       SWID Tags ID inventory as a JSON array
-     */
-    json_object* (*get_swid_inventory)(imv_swid_state_t *this);
+	/**
+	 * Get the encoding of the complete SWID Tag ID inventory
+	 *
+	 * @return			       SWID Tags ID inventory as a JSON array
+	 */
+	json_object* (*get_swid_inventory)(imv_swid_state_t *this);
 
 	/**
 	 * Set the number of still missing SWID Tags or Tag IDs
@@ -114,8 +114,10 @@ struct imv_swid_state_t {
 	 *
 	 * @param tag_id_count		Number of received SWID Tag IDs
 	 * @param tag_count			Number of received SWID Tags
+	 * @param imc_id			SWID IMC ID
 	 */
-	void (*set_count)(imv_swid_state_t *this, int tag_id_count, int tag_count);
+	void (*set_count)(imv_swid_state_t *this, int tag_id_count, int tag_count,
+					  TNC_UInt32 imc_id);
 
 	/**
 	 * Set [or with multiple attributes increment] SWID Tag [ID] counters
@@ -124,6 +126,13 @@ struct imv_swid_state_t {
 	 * @param tag_count			Number of received SWID Tags
 	 */
 	void (*get_count)(imv_swid_state_t *this, int *tag_id_count, int *tag_count);
+
+	/**
+	 * Get SWID IMC ID
+	 *
+	 * @return					SWID IMC ID
+	 */
+	TNC_UInt32 (*get_imc_id)(imv_swid_state_t *this);
 };
 
 /**
diff --git a/src/libimcv/plugins/imv_test/Makefile.in b/src/libimcv/plugins/imv_test/Makefile.in
index 8e0e223..19cef20 100644
--- a/src/libimcv/plugins/imv_test/Makefile.in
+++ b/src/libimcv/plugins/imv_test/Makefile.in
@@ -412,6 +412,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libimcv/pts/components/pts_component_manager.h b/src/libimcv/pts/components/pts_component_manager.h
index 61055ec..00f8765 100644
--- a/src/libimcv/pts/components/pts_component_manager.h
+++ b/src/libimcv/pts/components/pts_component_manager.h
@@ -45,7 +45,7 @@ struct pts_component_manager_t {
 	 * @param comp_func_names		Vendor-specific Component Functional names
 	 * @param qualifier_type_size	Vendor-specific Qualifier Type size
 	 * @param qualifier_flag_names	Vendor-specific Qualifier Flag names
-	 * @param qualifier_type_names	Vendor-specific Qualifier Type names 
+	 * @param qualifier_type_names	Vendor-specific Qualifier Type names
 	 */
 	void (*add_vendor)(pts_component_manager_t *this, pen_t vendor_id,
 					   enum_name_t *comp_func_names,
@@ -106,7 +106,7 @@ struct pts_component_manager_t {
 	 * @param pts_db				PTS measurement database
 	 * @return						Component object if supported, NULL else
 	 */
-	pts_component_t* (*create)(pts_component_manager_t *this, 
+	pts_component_t* (*create)(pts_component_manager_t *this,
 							   pts_comp_func_name_t *name, u_int32_t depth,
 							   pts_database_t *pts_db);
 
diff --git a/src/libipsec/Makefile.in b/src/libipsec/Makefile.in
index aa79344..a08d8c5 100644
--- a/src/libipsec/Makefile.in
+++ b/src/libipsec/Makefile.in
@@ -453,6 +453,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libipsec/ipsec_policy_mgr.c b/src/libipsec/ipsec_policy_mgr.c
index e2eaba0..3f312ff 100644
--- a/src/libipsec/ipsec_policy_mgr.c
+++ b/src/libipsec/ipsec_policy_mgr.c
@@ -175,15 +175,16 @@ METHOD(ipsec_policy_mgr_t, add_policy, status_t,
 }
 
 METHOD(ipsec_policy_mgr_t, del_policy, status_t,
-	private_ipsec_policy_mgr_t *this, traffic_selector_t *src_ts,
-	traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t reqid,
-	mark_t mark, policy_priority_t policy_priority)
+	private_ipsec_policy_mgr_t *this, host_t *src, host_t *dst,
+	traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
+	policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, mark_t mark,
+	policy_priority_t policy_priority)
 {
 	enumerator_t *enumerator;
 	ipsec_policy_entry_t *current, *found = NULL;
 	u_int32_t priority;
 
-	if (direction == POLICY_FWD)
+	if (type != POLICY_IPSEC || direction == POLICY_FWD)
 	{	/* we ignore these policies as we currently have no use for them */
 		return SUCCESS;
 	}
@@ -198,7 +199,7 @@ METHOD(ipsec_policy_mgr_t, del_policy, status_t,
 	{
 		if (current->priority == priority &&
 			current->policy->match(current->policy, src_ts, dst_ts, direction,
-								   reqid, mark, policy_priority))
+								   sa->reqid, mark, policy_priority))
 		{
 			this->policies->remove_at(this->policies, enumerator);
 			found = current;
diff --git a/src/libipsec/ipsec_policy_mgr.h b/src/libipsec/ipsec_policy_mgr.h
index 30406bd..0ea797e 100644
--- a/src/libipsec/ipsec_policy_mgr.h
+++ b/src/libipsec/ipsec_policy_mgr.h
@@ -71,18 +71,21 @@ struct ipsec_policy_mgr_t {
 	/**
 	 * Remove a policy
 	 *
+	 * @param src			source address of SA
+	 * @param dst			dest address of SA
 	 * @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|OUT|FWD)
-	 * @param reqid			unique ID of the associated SA
+	 * @param type			type of policy, POLICY_(IPSEC|PASS|DROP)
+	 * @param sa			details about the SA(s) tied to this policy
 	 * @param mark			optional mark
 	 * @param priority		priority of the policy
 	 * @return				SUCCESS if operation completed
 	 */
 	status_t (*del_policy)(ipsec_policy_mgr_t *this,
-						   traffic_selector_t *src_ts,
-						   traffic_selector_t *dst_ts,
-						   policy_dir_t direction, u_int32_t reqid, mark_t mark,
+						   host_t *src, host_t *dst, traffic_selector_t *src_ts,
+						   traffic_selector_t *dst_ts, policy_dir_t direction,
+						   policy_type_t type, ipsec_sa_cfg_t *sa, mark_t mark,
 						   policy_priority_t priority);
 
 	/**
diff --git a/src/libipsec/tests/Makefile.in b/src/libipsec/tests/Makefile.in
index 9a9bb31..ebf6e7e 100644
--- a/src/libipsec/tests/Makefile.in
+++ b/src/libipsec/tests/Makefile.in
@@ -409,6 +409,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libpttls/Makefile.in b/src/libpttls/Makefile.in
index 96d1ae4..c4eb8b4 100644
--- a/src/libpttls/Makefile.in
+++ b/src/libpttls/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libradius/Makefile.in b/src/libradius/Makefile.in
index 9bca3bd..9b03099 100644
--- a/src/libradius/Makefile.in
+++ b/src/libradius/Makefile.in
@@ -409,6 +409,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libsimaka/Makefile.am b/src/libsimaka/Makefile.am
index 9997ece..dd31689 100644
--- a/src/libsimaka/Makefile.am
+++ b/src/libsimaka/Makefile.am
@@ -1,6 +1,5 @@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_LDFLAGS = \
diff --git a/src/libsimaka/Makefile.in b/src/libsimaka/Makefile.in
index 637137c..e813eb0 100644
--- a/src/libsimaka/Makefile.in
+++ b/src/libsimaka/Makefile.in
@@ -412,6 +412,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -427,7 +429,6 @@ xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon
 
 AM_LDFLAGS = \
diff --git a/src/libstrongswan/Android.mk b/src/libstrongswan/Android.mk
index db3da8e..da5f34e 100644
--- a/src/libstrongswan/Android.mk
+++ b/src/libstrongswan/Android.mk
@@ -21,7 +21,8 @@ credentials/credential_factory.c credentials/builder.c \
 credentials/cred_encoding.c credentials/keys/private_key.c \
 credentials/keys/public_key.c credentials/keys/shared_key.c \
 credentials/certificates/certificate.c credentials/certificates/crl.c \
-credentials/certificates/ocsp_response.c \
+credentials/certificates/ocsp_response.c credentials/certificates/x509.c \
+credentials/certificates/certificate_printer.c \
 credentials/containers/container.c credentials/containers/pkcs12.c \
 credentials/credential_manager.c \
 credentials/sets/auth_cfg_wrapper.c credentials/sets/ocsp_response_wrapper.c \
diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am
index ed3b85d..0bac61b 100644
--- a/src/libstrongswan/Makefile.am
+++ b/src/libstrongswan/Makefile.am
@@ -19,7 +19,8 @@ credentials/credential_factory.c credentials/builder.c \
 credentials/cred_encoding.c credentials/keys/private_key.c \
 credentials/keys/public_key.c credentials/keys/shared_key.c \
 credentials/certificates/certificate.c credentials/certificates/crl.c \
-credentials/certificates/ocsp_response.c \
+credentials/certificates/ocsp_response.c credentials/certificates/x509.c \
+credentials/certificates/certificate_printer.c \
 credentials/containers/container.c credentials/containers/pkcs12.c \
 credentials/credential_manager.c \
 credentials/sets/auth_cfg_wrapper.c credentials/sets/ocsp_response_wrapper.c \
@@ -83,6 +84,7 @@ credentials/certificates/ac.h credentials/certificates/crl.h \
 credentials/certificates/pkcs10.h credentials/certificates/ocsp_request.h \
 credentials/certificates/ocsp_response.h \
 credentials/certificates/pgp_certificate.h \
+credentials/certificates/certificate_printer.h \
 credentials/containers/container.h credentials/containers/pkcs7.h \
 credentials/containers/pkcs12.h \
 credentials/credential_manager.h credentials/sets/auth_cfg_wrapper.h \
diff --git a/src/libstrongswan/Makefile.in b/src/libstrongswan/Makefile.in
index 284960f..d88c96f 100644
--- a/src/libstrongswan/Makefile.in
+++ b/src/libstrongswan/Makefile.in
@@ -322,6 +322,8 @@ am__libstrongswan_la_SOURCES_DIST = library.c asn1/asn1.c \
 	credentials/certificates/certificate.c \
 	credentials/certificates/crl.c \
 	credentials/certificates/ocsp_response.c \
+	credentials/certificates/x509.c \
+	credentials/certificates/certificate_printer.c \
 	credentials/containers/container.c \
 	credentials/containers/pkcs12.c \
 	credentials/credential_manager.c \
@@ -407,6 +409,8 @@ am_libstrongswan_la_OBJECTS = library.lo asn1/asn1.lo \
 	credentials/certificates/certificate.lo \
 	credentials/certificates/crl.lo \
 	credentials/certificates/ocsp_response.lo \
+	credentials/certificates/x509.lo \
+	credentials/certificates/certificate_printer.lo \
 	credentials/containers/container.lo \
 	credentials/containers/pkcs12.lo \
 	credentials/credential_manager.lo \
@@ -539,6 +543,7 @@ am__nobase_strongswan_include_HEADERS_DIST = library.h asn1/asn1.h \
 	credentials/certificates/ocsp_request.h \
 	credentials/certificates/ocsp_response.h \
 	credentials/certificates/pgp_certificate.h \
+	credentials/certificates/certificate_printer.h \
 	credentials/containers/container.h \
 	credentials/containers/pkcs7.h credentials/containers/pkcs12.h \
 	credentials/credential_manager.h \
@@ -865,6 +870,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -900,6 +907,8 @@ libstrongswan_la_SOURCES = library.c asn1/asn1.c asn1/asn1_parser.c \
 	credentials/certificates/certificate.c \
 	credentials/certificates/crl.c \
 	credentials/certificates/ocsp_response.c \
+	credentials/certificates/x509.c \
+	credentials/certificates/certificate_printer.c \
 	credentials/containers/container.c \
 	credentials/containers/pkcs12.c \
 	credentials/credential_manager.c \
@@ -961,6 +970,7 @@ settings/settings_types.h
 @USE_DEV_HEADERS_TRUE at credentials/certificates/pkcs10.h credentials/certificates/ocsp_request.h \
 @USE_DEV_HEADERS_TRUE at credentials/certificates/ocsp_response.h \
 @USE_DEV_HEADERS_TRUE at credentials/certificates/pgp_certificate.h \
+ at USE_DEV_HEADERS_TRUE@credentials/certificates/certificate_printer.h \
 @USE_DEV_HEADERS_TRUE at credentials/containers/container.h credentials/containers/pkcs7.h \
 @USE_DEV_HEADERS_TRUE at credentials/containers/pkcs12.h \
 @USE_DEV_HEADERS_TRUE at credentials/credential_manager.h credentials/sets/auth_cfg_wrapper.h \
@@ -1341,6 +1351,12 @@ credentials/certificates/crl.lo:  \
 credentials/certificates/ocsp_response.lo:  \
 	credentials/certificates/$(am__dirstamp) \
 	credentials/certificates/$(DEPDIR)/$(am__dirstamp)
+credentials/certificates/x509.lo:  \
+	credentials/certificates/$(am__dirstamp) \
+	credentials/certificates/$(DEPDIR)/$(am__dirstamp)
+credentials/certificates/certificate_printer.lo:  \
+	credentials/certificates/$(am__dirstamp) \
+	credentials/certificates/$(DEPDIR)/$(am__dirstamp)
 credentials/containers/$(am__dirstamp):
 	@$(MKDIR_P) credentials/containers
 	@: > credentials/containers/$(am__dirstamp)
@@ -1735,8 +1751,10 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at credentials/$(DEPDIR)/credential_factory.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at credentials/$(DEPDIR)/credential_manager.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at credentials/certificates/$(DEPDIR)/certificate.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at credentials/certificates/$(DEPDIR)/certificate_printer.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at credentials/certificates/$(DEPDIR)/crl.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at credentials/certificates/$(DEPDIR)/ocsp_response.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at credentials/certificates/$(DEPDIR)/x509.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at credentials/containers/$(DEPDIR)/container.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at credentials/containers/$(DEPDIR)/pkcs12.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at credentials/keys/$(DEPDIR)/private_key.Plo at am__quote@
diff --git a/src/libstrongswan/asn1/asn1.h b/src/libstrongswan/asn1/asn1.h
index 7a48292..8ac0056 100644
--- a/src/libstrongswan/asn1/asn1.h
+++ b/src/libstrongswan/asn1/asn1.h
@@ -26,6 +26,7 @@
 #include <stdarg.h>
 
 #include <library.h>
+#include <asn1/asn1.h>
 
 /**
  * Definition of some primitive ASN1 types
diff --git a/src/libstrongswan/asn1/oid.c b/src/libstrongswan/asn1/oid.c
index a088b05..ed953d4 100644
--- a/src/libstrongswan/asn1/oid.c
+++ b/src/libstrongswan/asn1/oid.c
@@ -28,8 +28,8 @@ const oid_t oid_names[] = {
  {                0x01,         0, 1,  8, "pilotAttributeType"             }, /*  15 */
  {                  0x01,      17, 0,  9, "UID"                            }, /*  16 */
  {                  0x19,       0, 0,  9, "DC"                             }, /*  17 */
- {0x55,                        65, 1,  0, "X.500"                          }, /*  18 */
- {  0x04,                      37, 1,  1, "X.509"                          }, /*  19 */
+ {0x55,                        66, 1,  0, "X.500"                          }, /*  18 */
+ {  0x04,                      38, 1,  1, "X.509"                          }, /*  19 */
  {    0x03,                    21, 0,  2, "CN"                             }, /*  20 */
  {    0x04,                    22, 0,  2, "S"                              }, /*  21 */
  {    0x05,                    23, 0,  2, "SN"                             }, /*  22 */
@@ -46,446 +46,447 @@ const oid_t oid_names[] = {
  {    0x2B,                    34, 0,  2, "I"                              }, /*  33 */
  {    0x2D,                    35, 0,  2, "ID"                             }, /*  34 */
  {    0x2E,                    36, 0,  2, "dnQualifier"                    }, /*  35 */
- {    0x48,                     0, 0,  2, "role"                           }, /*  36 */
- {  0x1D,                       0, 1,  1, "id-ce"                          }, /*  37 */
- {    0x09,                    39, 0,  2, "subjectDirectoryAttrs"          }, /*  38 */
- {    0x0E,                    40, 0,  2, "subjectKeyIdentifier"           }, /*  39 */
- {    0x0F,                    41, 0,  2, "keyUsage"                       }, /*  40 */
- {    0x10,                    42, 0,  2, "privateKeyUsagePeriod"          }, /*  41 */
- {    0x11,                    43, 0,  2, "subjectAltName"                 }, /*  42 */
- {    0x12,                    44, 0,  2, "issuerAltName"                  }, /*  43 */
- {    0x13,                    45, 0,  2, "basicConstraints"               }, /*  44 */
- {    0x14,                    46, 0,  2, "crlNumber"                      }, /*  45 */
- {    0x15,                    47, 0,  2, "reasonCode"                     }, /*  46 */
- {    0x17,                    48, 0,  2, "holdInstructionCode"            }, /*  47 */
- {    0x18,                    49, 0,  2, "invalidityDate"                 }, /*  48 */
- {    0x1B,                    50, 0,  2, "deltaCrlIndicator"              }, /*  49 */
- {    0x1C,                    51, 0,  2, "issuingDistributionPoint"       }, /*  50 */
- {    0x1D,                    52, 0,  2, "certificateIssuer"              }, /*  51 */
- {    0x1E,                    53, 0,  2, "nameConstraints"                }, /*  52 */
- {    0x1F,                    54, 0,  2, "crlDistributionPoints"          }, /*  53 */
- {    0x20,                    56, 1,  2, "certificatePolicies"            }, /*  54 */
- {      0x00,                   0, 0,  3, "anyPolicy"                      }, /*  55 */
- {    0x21,                    57, 0,  2, "policyMappings"                 }, /*  56 */
- {    0x23,                    58, 0,  2, "authorityKeyIdentifier"         }, /*  57 */
- {    0x24,                    59, 0,  2, "policyConstraints"              }, /*  58 */
- {    0x25,                    61, 1,  2, "extendedKeyUsage"               }, /*  59 */
- {      0x00,                   0, 0,  3, "anyExtendedKeyUsage"            }, /*  60 */
- {    0x2E,                    62, 0,  2, "freshestCRL"                    }, /*  61 */
- {    0x36,                    63, 0,  2, "inhibitAnyPolicy"               }, /*  62 */
- {    0x37,                    64, 0,  2, "targetInformation"              }, /*  63 */
- {    0x38,                     0, 0,  2, "noRevAvail"                     }, /*  64 */
- {0x2A,                       189, 1,  0, ""                               }, /*  65 */
- {  0x83,                      78, 1,  1, ""                               }, /*  66 */
- {    0x08,                     0, 1,  2, "jp"                             }, /*  67 */
- {      0x8C,                   0, 1,  3, ""                               }, /*  68 */
- {        0x9A,                 0, 1,  4, ""                               }, /*  69 */
- {          0x4B,               0, 1,  5, ""                               }, /*  70 */
- {            0x3D,             0, 1,  6, ""                               }, /*  71 */
- {              0x01,           0, 1,  7, "security"                       }, /*  72 */
- {                0x01,         0, 1,  8, "algorithm"                      }, /*  73 */
- {                  0x01,       0, 1,  9, "symm-encryption-alg"            }, /*  74 */
- {                    0x02,    76, 0, 10, "camellia128-cbc"                }, /*  75 */
- {                    0x03,    77, 0, 10, "camellia192-cbc"                }, /*  76 */
- {                    0x04,     0, 0, 10, "camellia256-cbc"                }, /*  77 */
- {  0x86,                       0, 1,  1, ""                               }, /*  78 */
- {    0x48,                     0, 1,  2, "us"                             }, /*  79 */
- {      0x86,                 148, 1,  3, ""                               }, /*  80 */
- {        0xF6,                86, 1,  4, ""                               }, /*  81 */
- {          0x7D,               0, 1,  5, "NortelNetworks"                 }, /*  82 */
- {            0x07,             0, 1,  6, "Entrust"                        }, /*  83 */
- {              0x41,           0, 1,  7, "nsn-ce"                         }, /*  84 */
- {                0x00,         0, 0,  8, "entrustVersInfo"                }, /*  85 */
- {        0xF7,                 0, 1,  4, ""                               }, /*  86 */
- {          0x0D,               0, 1,  5, "RSADSI"                         }, /*  87 */
- {            0x01,           143, 1,  6, "PKCS"                           }, /*  88 */
- {              0x01,         101, 1,  7, "PKCS-1"                         }, /*  89 */
- {                0x01,        91, 0,  8, "rsaEncryption"                  }, /*  90 */
- {                0x02,        92, 0,  8, "md2WithRSAEncryption"           }, /*  91 */
- {                0x04,        93, 0,  8, "md5WithRSAEncryption"           }, /*  92 */
- {                0x05,        94, 0,  8, "sha-1WithRSAEncryption"         }, /*  93 */
- {                0x07,        95, 0,  8, "id-RSAES-OAEP"                  }, /*  94 */
- {                0x08,        96, 0,  8, "id-mgf1"                        }, /*  95 */
- {                0x09,        97, 0,  8, "id-pSpecified"                  }, /*  96 */
- {                0x0B,        98, 0,  8, "sha256WithRSAEncryption"        }, /*  97 */
- {                0x0C,        99, 0,  8, "sha384WithRSAEncryption"        }, /*  98 */
- {                0x0D,       100, 0,  8, "sha512WithRSAEncryption"        }, /*  99 */
- {                0x0E,         0, 0,  8, "sha224WithRSAEncryption"        }, /* 100 */
- {              0x05,         106, 1,  7, "PKCS-5"                         }, /* 101 */
- {                0x03,       103, 0,  8, "pbeWithMD5AndDES-CBC"           }, /* 102 */
- {                0x0A,       104, 0,  8, "pbeWithSHA1AndDES-CBC"          }, /* 103 */
- {                0x0C,       105, 0,  8, "id-PBKDF2"                      }, /* 104 */
- {                0x0D,         0, 0,  8, "id-PBES2"                       }, /* 105 */
- {              0x07,         113, 1,  7, "PKCS-7"                         }, /* 106 */
- {                0x01,       108, 0,  8, "data"                           }, /* 107 */
- {                0x02,       109, 0,  8, "signedData"                     }, /* 108 */
- {                0x03,       110, 0,  8, "envelopedData"                  }, /* 109 */
- {                0x04,       111, 0,  8, "signedAndEnvelopedData"         }, /* 110 */
- {                0x05,       112, 0,  8, "digestedData"                   }, /* 111 */
- {                0x06,         0, 0,  8, "encryptedData"                  }, /* 112 */
- {              0x09,         127, 1,  7, "PKCS-9"                         }, /* 113 */
- {                0x01,       115, 0,  8, "E"                              }, /* 114 */
- {                0x02,       116, 0,  8, "unstructuredName"               }, /* 115 */
- {                0x03,       117, 0,  8, "contentType"                    }, /* 116 */
- {                0x04,       118, 0,  8, "messageDigest"                  }, /* 117 */
- {                0x05,       119, 0,  8, "signingTime"                    }, /* 118 */
- {                0x06,       120, 0,  8, "counterSignature"               }, /* 119 */
- {                0x07,       121, 0,  8, "challengePassword"              }, /* 120 */
- {                0x08,       122, 0,  8, "unstructuredAddress"            }, /* 121 */
- {                0x0E,       123, 0,  8, "extensionRequest"               }, /* 122 */
- {                0x0F,       124, 0,  8, "S/MIME Capabilities"            }, /* 123 */
- {                0x16,         0, 1,  8, "certTypes"                      }, /* 124 */
- {                  0x01,     126, 0,  9, "X.509"                          }, /* 125 */
- {                  0x02,       0, 0,  9, "SDSI"                           }, /* 126 */
- {              0x0c,           0, 1,  7, "PKCS-12"                        }, /* 127 */
- {                0x01,       135, 1,  8, "pbeIds"                         }, /* 128 */
- {                  0x01,     130, 0,  9, "pbeWithSHAAnd128BitRC4"         }, /* 129 */
- {                  0x02,     131, 0,  9, "pbeWithSHAAnd40BitRC4"          }, /* 130 */
- {                  0x03,     132, 0,  9, "pbeWithSHAAnd3-KeyTripleDES-CBC"}, /* 131 */
- {                  0x04,     133, 0,  9, "pbeWithSHAAnd2-KeyTripleDES-CBC"}, /* 132 */
- {                  0x05,     134, 0,  9, "pbeWithSHAAnd128BitRC2-CBC"     }, /* 133 */
- {                  0x06,       0, 0,  9, "pbeWithSHAAnd40BitRC2-CBC"      }, /* 134 */
- {                0x0a,         0, 1,  8, "PKCS-12v1"                      }, /* 135 */
- {                  0x01,       0, 1,  9, "bagIds"                         }, /* 136 */
- {                    0x01,   138, 0, 10, "keyBag"                         }, /* 137 */
- {                    0x02,   139, 0, 10, "pkcs8ShroudedKeyBag"            }, /* 138 */
- {                    0x03,   140, 0, 10, "certBag"                        }, /* 139 */
- {                    0x04,   141, 0, 10, "crlBag"                         }, /* 140 */
- {                    0x05,   142, 0, 10, "secretBag"                      }, /* 141 */
- {                    0x06,     0, 0, 10, "safeContentsBag"                }, /* 142 */
- {            0x02,           146, 1,  6, "digestAlgorithm"                }, /* 143 */
- {              0x02,         145, 0,  7, "md2"                            }, /* 144 */
- {              0x05,           0, 0,  7, "md5"                            }, /* 145 */
- {            0x03,             0, 1,  6, "encryptionAlgorithm"            }, /* 146 */
- {              0x07,           0, 0,  7, "3des-ede-cbc"                   }, /* 147 */
- {      0xCE,                   0, 1,  3, ""                               }, /* 148 */
- {        0x3D,                 0, 1,  4, "ansi-X9-62"                     }, /* 149 */
- {          0x02,             152, 1,  5, "id-publicKeyType"               }, /* 150 */
- {            0x01,             0, 0,  6, "id-ecPublicKey"                 }, /* 151 */
- {          0x03,             182, 1,  5, "ellipticCurve"                  }, /* 152 */
- {            0x00,           174, 1,  6, "c-TwoCurve"                     }, /* 153 */
- {              0x01,         155, 0,  7, "c2pnb163v1"                     }, /* 154 */
- {              0x02,         156, 0,  7, "c2pnb163v2"                     }, /* 155 */
- {              0x03,         157, 0,  7, "c2pnb163v3"                     }, /* 156 */
- {              0x04,         158, 0,  7, "c2pnb176w1"                     }, /* 157 */
- {              0x05,         159, 0,  7, "c2tnb191v1"                     }, /* 158 */
- {              0x06,         160, 0,  7, "c2tnb191v2"                     }, /* 159 */
- {              0x07,         161, 0,  7, "c2tnb191v3"                     }, /* 160 */
- {              0x08,         162, 0,  7, "c2onb191v4"                     }, /* 161 */
- {              0x09,         163, 0,  7, "c2onb191v5"                     }, /* 162 */
- {              0x0A,         164, 0,  7, "c2pnb208w1"                     }, /* 163 */
- {              0x0B,         165, 0,  7, "c2tnb239v1"                     }, /* 164 */
- {              0x0C,         166, 0,  7, "c2tnb239v2"                     }, /* 165 */
- {              0x0D,         167, 0,  7, "c2tnb239v3"                     }, /* 166 */
- {              0x0E,         168, 0,  7, "c2onb239v4"                     }, /* 167 */
- {              0x0F,         169, 0,  7, "c2onb239v5"                     }, /* 168 */
- {              0x10,         170, 0,  7, "c2pnb272w1"                     }, /* 169 */
- {              0x11,         171, 0,  7, "c2pnb304w1"                     }, /* 170 */
- {              0x12,         172, 0,  7, "c2tnb359v1"                     }, /* 171 */
- {              0x13,         173, 0,  7, "c2pnb368w1"                     }, /* 172 */
- {              0x14,           0, 0,  7, "c2tnb431r1"                     }, /* 173 */
- {            0x01,             0, 1,  6, "primeCurve"                     }, /* 174 */
- {              0x01,         176, 0,  7, "prime192v1"                     }, /* 175 */
- {              0x02,         177, 0,  7, "prime192v2"                     }, /* 176 */
- {              0x03,         178, 0,  7, "prime192v3"                     }, /* 177 */
- {              0x04,         179, 0,  7, "prime239v1"                     }, /* 178 */
- {              0x05,         180, 0,  7, "prime239v2"                     }, /* 179 */
- {              0x06,         181, 0,  7, "prime239v3"                     }, /* 180 */
- {              0x07,           0, 0,  7, "prime256v1"                     }, /* 181 */
- {          0x04,               0, 1,  5, "id-ecSigType"                   }, /* 182 */
- {            0x01,           184, 0,  6, "ecdsa-with-SHA1"                }, /* 183 */
- {            0x03,             0, 1,  6, "ecdsa-with-Specified"           }, /* 184 */
- {              0x01,         186, 0,  7, "ecdsa-with-SHA224"              }, /* 185 */
- {              0x02,         187, 0,  7, "ecdsa-with-SHA256"              }, /* 186 */
- {              0x03,         188, 0,  7, "ecdsa-with-SHA384"              }, /* 187 */
- {              0x04,           0, 0,  7, "ecdsa-with-SHA512"              }, /* 188 */
- {0x2B,                       416, 1,  0, ""                               }, /* 189 */
- {  0x06,                     330, 1,  1, "dod"                            }, /* 190 */
- {    0x01,                     0, 1,  2, "internet"                       }, /* 191 */
- {      0x04,                 281, 1,  3, "private"                        }, /* 192 */
- {        0x01,                 0, 1,  4, "enterprise"                     }, /* 193 */
- {          0x82,             231, 1,  5, ""                               }, /* 194 */
- {            0x37,           207, 1,  6, "Microsoft"                      }, /* 195 */
- {              0x0A,         200, 1,  7, ""                               }, /* 196 */
- {                0x03,         0, 1,  8, ""                               }, /* 197 */
- {                  0x03,     199, 0,  9, "msSGC"                          }, /* 198 */
- {                  0x04,       0, 0,  9, "msEncryptingFileSystem"         }, /* 199 */
- {              0x14,         204, 1,  7, "msEnrollmentInfrastructure"     }, /* 200 */
- {                0x02,         0, 1,  8, "msCertificateTypeExtension"     }, /* 201 */
- {                  0x02,     203, 0,  9, "msSmartcardLogon"               }, /* 202 */
- {                  0x03,       0, 0,  9, "msUPN"                          }, /* 203 */
- {              0x15,           0, 1,  7, "msCertSrvInfrastructure"        }, /* 204 */
- {                0x07,       206, 0,  8, "msCertTemplate"                 }, /* 205 */
- {                0x0A,         0, 0,  8, "msApplicationCertPolicies"      }, /* 206 */
- {            0xA0,             0, 1,  6, ""                               }, /* 207 */
- {              0x2A,           0, 1,  7, "ITA"                            }, /* 208 */
- {                0x01,       210, 0,  8, "strongSwan"                     }, /* 209 */
- {                0x02,       211, 0,  8, "cps"                            }, /* 210 */
- {                0x03,       212, 0,  8, "e-voting"                       }, /* 211 */
- {                0x05,         0, 1,  8, "BLISS"                          }, /* 212 */
- {                  0x01,     215, 1,  9, "keyType"                        }, /* 213 */
- {                    0x01,     0, 0, 10, "blissPublicKey"                 }, /* 214 */
- {                  0x02,     224, 1,  9, "parameters"                     }, /* 215 */
- {                    0x01,   217, 0, 10, "BLISS-I"                        }, /* 216 */
- {                    0x02,   218, 0, 10, "BLISS-II"                       }, /* 217 */
- {                    0x03,   219, 0, 10, "BLISS-III"                      }, /* 218 */
- {                    0x04,   220, 0, 10, "BLISS-IV"                       }, /* 219 */
- {                    0x05,   221, 0, 10, "BLISS-B-I"                      }, /* 220 */
- {                    0x06,   222, 0, 10, "BLISS-B-II"                     }, /* 221 */
- {                    0x07,   223, 0, 10, "BLISS-B-III"                    }, /* 222 */
- {                    0x08,     0, 0, 10, "BLISS-B-IV"                     }, /* 223 */
- {                  0x03,       0, 1,  9, "blissSigType"                   }, /* 224 */
- {                    0x01,   226, 0, 10, "BLISS-with-SHA2-512"            }, /* 225 */
- {                    0x02,   227, 0, 10, "BLISS-with-SHA2-384"            }, /* 226 */
- {                    0x03,   228, 0, 10, "BLISS-with-SHA2-256"            }, /* 227 */
- {                    0x04,   229, 0, 10, "BLISS-with-SHA3-512"            }, /* 228 */
- {                    0x05,   230, 0, 10, "BLISS-with-SHA3-384"            }, /* 229 */
- {                    0x06,     0, 0, 10, "BLISS-with-SHA3-256"            }, /* 230 */
- {          0x89,             238, 1,  5, ""                               }, /* 231 */
- {            0x31,             0, 1,  6, ""                               }, /* 232 */
- {              0x01,           0, 1,  7, ""                               }, /* 233 */
- {                0x01,         0, 1,  8, ""                               }, /* 234 */
- {                  0x02,       0, 1,  9, ""                               }, /* 235 */
- {                    0x02,     0, 1, 10, ""                               }, /* 236 */
- {                      0x4B,   0, 0, 11, "TCGID"                          }, /* 237 */
- {          0x97,             242, 1,  5, ""                               }, /* 238 */
- {            0x55,             0, 1,  6, ""                               }, /* 239 */
- {              0x01,           0, 1,  7, ""                               }, /* 240 */
- {                0x02,         0, 0,  8, "blowfish-cbc"                   }, /* 241 */
- {          0xC1,               0, 1,  5, ""                               }, /* 242 */
- {            0x16,             0, 1,  6, "ntruCryptosystems"              }, /* 243 */
- {              0x01,           0, 1,  7, "eess"                           }, /* 244 */
- {                0x01,         0, 1,  8, "eess1"                          }, /* 245 */
- {                  0x01,     250, 1,  9, "eess1-algs"                     }, /* 246 */
- {                    0x01,   248, 0, 10, "ntru-EESS1v1-SVES"              }, /* 247 */
- {                    0x02,   249, 0, 10, "ntru-EESS1v1-SVSSA"             }, /* 248 */
- {                    0x03,     0, 0, 10, "ntru-EESS1v1-NTRUSign"          }, /* 249 */
- {                  0x02,     280, 1,  9, "eess1-params"                   }, /* 250 */
- {                    0x01,   252, 0, 10, "ees251ep1"                      }, /* 251 */
- {                    0x02,   253, 0, 10, "ees347ep1"                      }, /* 252 */
- {                    0x03,   254, 0, 10, "ees503ep1"                      }, /* 253 */
- {                    0x07,   255, 0, 10, "ees251sp2"                      }, /* 254 */
- {                    0x0C,   256, 0, 10, "ees251ep4"                      }, /* 255 */
- {                    0x0D,   257, 0, 10, "ees251ep5"                      }, /* 256 */
- {                    0x0E,   258, 0, 10, "ees251sp3"                      }, /* 257 */
- {                    0x0F,   259, 0, 10, "ees251sp4"                      }, /* 258 */
- {                    0x10,   260, 0, 10, "ees251sp5"                      }, /* 259 */
- {                    0x11,   261, 0, 10, "ees251sp6"                      }, /* 260 */
- {                    0x12,   262, 0, 10, "ees251sp7"                      }, /* 261 */
- {                    0x13,   263, 0, 10, "ees251sp8"                      }, /* 262 */
- {                    0x14,   264, 0, 10, "ees251sp9"                      }, /* 263 */
- {                    0x22,   265, 0, 10, "ees401ep1"                      }, /* 264 */
- {                    0x23,   266, 0, 10, "ees449ep1"                      }, /* 265 */
- {                    0x24,   267, 0, 10, "ees677ep1"                      }, /* 266 */
- {                    0x25,   268, 0, 10, "ees1087ep2"                     }, /* 267 */
- {                    0x26,   269, 0, 10, "ees541ep1"                      }, /* 268 */
- {                    0x27,   270, 0, 10, "ees613ep1"                      }, /* 269 */
- {                    0x28,   271, 0, 10, "ees887ep1"                      }, /* 270 */
- {                    0x29,   272, 0, 10, "ees1171ep1"                     }, /* 271 */
- {                    0x2A,   273, 0, 10, "ees659ep1"                      }, /* 272 */
- {                    0x2B,   274, 0, 10, "ees761ep1"                      }, /* 273 */
- {                    0x2C,   275, 0, 10, "ees1087ep1"                     }, /* 274 */
- {                    0x2D,   276, 0, 10, "ees1499ep1"                     }, /* 275 */
- {                    0x2E,   277, 0, 10, "ees401ep2"                      }, /* 276 */
- {                    0x2F,   278, 0, 10, "ees439ep1"                      }, /* 277 */
- {                    0x30,   279, 0, 10, "ees593ep1"                      }, /* 278 */
- {                    0x31,     0, 0, 10, "ees743ep1"                      }, /* 279 */
- {                  0x03,       0, 0,  9, "eess1-encodingMethods"          }, /* 280 */
- {      0x05,                   0, 1,  3, "security"                       }, /* 281 */
- {        0x05,                 0, 1,  4, "mechanisms"                     }, /* 282 */
- {          0x07,             327, 1,  5, "id-pkix"                        }, /* 283 */
- {            0x01,           288, 1,  6, "id-pe"                          }, /* 284 */
- {              0x01,         286, 0,  7, "authorityInfoAccess"            }, /* 285 */
- {              0x03,         287, 0,  7, "qcStatements"                   }, /* 286 */
- {              0x07,           0, 0,  7, "ipAddrBlocks"                   }, /* 287 */
- {            0x02,           291, 1,  6, "id-qt"                          }, /* 288 */
- {              0x01,         290, 0,  7, "cps"                            }, /* 289 */
- {              0x02,           0, 0,  7, "unotice"                        }, /* 290 */
- {            0x03,           301, 1,  6, "id-kp"                          }, /* 291 */
- {              0x01,         293, 0,  7, "serverAuth"                     }, /* 292 */
- {              0x02,         294, 0,  7, "clientAuth"                     }, /* 293 */
- {              0x03,         295, 0,  7, "codeSigning"                    }, /* 294 */
- {              0x04,         296, 0,  7, "emailProtection"                }, /* 295 */
- {              0x05,         297, 0,  7, "ipsecEndSystem"                 }, /* 296 */
- {              0x06,         298, 0,  7, "ipsecTunnel"                    }, /* 297 */
- {              0x07,         299, 0,  7, "ipsecUser"                      }, /* 298 */
- {              0x08,         300, 0,  7, "timeStamping"                   }, /* 299 */
- {              0x09,           0, 0,  7, "ocspSigning"                    }, /* 300 */
- {            0x08,           309, 1,  6, "id-otherNames"                  }, /* 301 */
- {              0x01,         303, 0,  7, "personalData"                   }, /* 302 */
- {              0x02,         304, 0,  7, "userGroup"                      }, /* 303 */
- {              0x03,         305, 0,  7, "id-on-permanentIdentifier"      }, /* 304 */
- {              0x04,         306, 0,  7, "id-on-hardwareModuleName"       }, /* 305 */
- {              0x05,         307, 0,  7, "xmppAddr"                       }, /* 306 */
- {              0x06,         308, 0,  7, "id-on-SIM"                      }, /* 307 */
- {              0x07,           0, 0,  7, "id-on-dnsSRV"                   }, /* 308 */
- {            0x0A,           314, 1,  6, "id-aca"                         }, /* 309 */
- {              0x01,         311, 0,  7, "authenticationInfo"             }, /* 310 */
- {              0x02,         312, 0,  7, "accessIdentity"                 }, /* 311 */
- {              0x03,         313, 0,  7, "chargingIdentity"               }, /* 312 */
- {              0x04,           0, 0,  7, "group"                          }, /* 313 */
- {            0x0B,           315, 0,  6, "subjectInfoAccess"              }, /* 314 */
- {            0x30,             0, 1,  6, "id-ad"                          }, /* 315 */
- {              0x01,         324, 1,  7, "ocsp"                           }, /* 316 */
- {                0x01,       318, 0,  8, "basic"                          }, /* 317 */
- {                0x02,       319, 0,  8, "nonce"                          }, /* 318 */
- {                0x03,       320, 0,  8, "crl"                            }, /* 319 */
- {                0x04,       321, 0,  8, "response"                       }, /* 320 */
- {                0x05,       322, 0,  8, "noCheck"                        }, /* 321 */
- {                0x06,       323, 0,  8, "archiveCutoff"                  }, /* 322 */
- {                0x07,         0, 0,  8, "serviceLocator"                 }, /* 323 */
- {              0x02,         325, 0,  7, "caIssuers"                      }, /* 324 */
- {              0x03,         326, 0,  7, "timeStamping"                   }, /* 325 */
- {              0x05,           0, 0,  7, "caRepository"                   }, /* 326 */
- {          0x08,               0, 1,  5, "ipsec"                          }, /* 327 */
- {            0x02,             0, 1,  6, "certificate"                    }, /* 328 */
- {              0x02,           0, 0,  7, "iKEIntermediate"                }, /* 329 */
- {  0x0E,                     336, 1,  1, "oiw"                            }, /* 330 */
- {    0x03,                     0, 1,  2, "secsig"                         }, /* 331 */
- {      0x02,                   0, 1,  3, "algorithms"                     }, /* 332 */
- {        0x07,               334, 0,  4, "des-cbc"                        }, /* 333 */
- {        0x1A,               335, 0,  4, "sha-1"                          }, /* 334 */
- {        0x1D,                 0, 0,  4, "sha-1WithRSASignature"          }, /* 335 */
- {  0x24,                     382, 1,  1, "TeleTrusT"                      }, /* 336 */
- {    0x03,                     0, 1,  2, "algorithm"                      }, /* 337 */
- {      0x03,                   0, 1,  3, "signatureAlgorithm"             }, /* 338 */
- {        0x01,               343, 1,  4, "rsaSignature"                   }, /* 339 */
- {          0x02,             341, 0,  5, "rsaSigWithripemd160"            }, /* 340 */
- {          0x03,             342, 0,  5, "rsaSigWithripemd128"            }, /* 341 */
- {          0x04,               0, 0,  5, "rsaSigWithripemd256"            }, /* 342 */
- {        0x02,                 0, 1,  4, "ecSign"                         }, /* 343 */
- {          0x01,             345, 0,  5, "ecSignWithsha1"                 }, /* 344 */
- {          0x02,             346, 0,  5, "ecSignWithripemd160"            }, /* 345 */
- {          0x03,             347, 0,  5, "ecSignWithmd2"                  }, /* 346 */
- {          0x04,             348, 0,  5, "ecSignWithmd5"                  }, /* 347 */
- {          0x05,             365, 1,  5, "ttt-ecg"                        }, /* 348 */
- {            0x01,           353, 1,  6, "fieldType"                      }, /* 349 */
- {              0x01,           0, 1,  7, "characteristictwoField"         }, /* 350 */
- {                0x01,         0, 1,  8, "basisType"                      }, /* 351 */
- {                  0x01,       0, 0,  9, "ipBasis"                        }, /* 352 */
- {            0x02,           355, 1,  6, "keyType"                        }, /* 353 */
- {              0x01,           0, 0,  7, "ecgPublicKey"                   }, /* 354 */
- {            0x03,           356, 0,  6, "curve"                          }, /* 355 */
- {            0x04,           363, 1,  6, "signatures"                     }, /* 356 */
- {              0x01,         358, 0,  7, "ecgdsa-with-RIPEMD160"          }, /* 357 */
- {              0x02,         359, 0,  7, "ecgdsa-with-SHA1"               }, /* 358 */
- {              0x03,         360, 0,  7, "ecgdsa-with-SHA224"             }, /* 359 */
- {              0x04,         361, 0,  7, "ecgdsa-with-SHA256"             }, /* 360 */
- {              0x05,         362, 0,  7, "ecgdsa-with-SHA384"             }, /* 361 */
- {              0x06,           0, 0,  7, "ecgdsa-with-SHA512"             }, /* 362 */
- {            0x05,             0, 1,  6, "module"                         }, /* 363 */
- {              0x01,           0, 0,  7, "1"                              }, /* 364 */
- {          0x08,               0, 1,  5, "ecStdCurvesAndGeneration"       }, /* 365 */
- {            0x01,             0, 1,  6, "ellipticCurve"                  }, /* 366 */
- {              0x01,           0, 1,  7, "versionOne"                     }, /* 367 */
- {                0x01,       369, 0,  8, "brainpoolP160r1"                }, /* 368 */
- {                0x02,       370, 0,  8, "brainpoolP160t1"                }, /* 369 */
- {                0x03,       371, 0,  8, "brainpoolP192r1"                }, /* 370 */
- {                0x04,       372, 0,  8, "brainpoolP192t1"                }, /* 371 */
- {                0x05,       373, 0,  8, "brainpoolP224r1"                }, /* 372 */
- {                0x06,       374, 0,  8, "brainpoolP224t1"                }, /* 373 */
- {                0x07,       375, 0,  8, "brainpoolP256r1"                }, /* 374 */
- {                0x08,       376, 0,  8, "brainpoolP256t1"                }, /* 375 */
- {                0x09,       377, 0,  8, "brainpoolP320r1"                }, /* 376 */
- {                0x0A,       378, 0,  8, "brainpoolP320t1"                }, /* 377 */
- {                0x0B,       379, 0,  8, "brainpoolP384r1"                }, /* 378 */
- {                0x0C,       380, 0,  8, "brainpoolP384t1"                }, /* 379 */
- {                0x0D,       381, 0,  8, "brainpoolP512r1"                }, /* 380 */
- {                0x0E,         0, 0,  8, "brainpoolP512t1"                }, /* 381 */
- {  0x81,                       0, 1,  1, ""                               }, /* 382 */
- {    0x04,                     0, 1,  2, "Certicom"                       }, /* 383 */
- {      0x00,                   0, 1,  3, "curve"                          }, /* 384 */
- {        0x01,               386, 0,  4, "sect163k1"                      }, /* 385 */
- {        0x02,               387, 0,  4, "sect163r1"                      }, /* 386 */
- {        0x03,               388, 0,  4, "sect239k1"                      }, /* 387 */
- {        0x04,               389, 0,  4, "sect113r1"                      }, /* 388 */
- {        0x05,               390, 0,  4, "sect113r2"                      }, /* 389 */
- {        0x06,               391, 0,  4, "secp112r1"                      }, /* 390 */
- {        0x07,               392, 0,  4, "secp112r2"                      }, /* 391 */
- {        0x08,               393, 0,  4, "secp160r1"                      }, /* 392 */
- {        0x09,               394, 0,  4, "secp160k1"                      }, /* 393 */
- {        0x0A,               395, 0,  4, "secp256k1"                      }, /* 394 */
- {        0x0F,               396, 0,  4, "sect163r2"                      }, /* 395 */
- {        0x10,               397, 0,  4, "sect283k1"                      }, /* 396 */
- {        0x11,               398, 0,  4, "sect283r1"                      }, /* 397 */
- {        0x16,               399, 0,  4, "sect131r1"                      }, /* 398 */
- {        0x17,               400, 0,  4, "sect131r2"                      }, /* 399 */
- {        0x18,               401, 0,  4, "sect193r1"                      }, /* 400 */
- {        0x19,               402, 0,  4, "sect193r2"                      }, /* 401 */
- {        0x1A,               403, 0,  4, "sect233k1"                      }, /* 402 */
- {        0x1B,               404, 0,  4, "sect233r1"                      }, /* 403 */
- {        0x1C,               405, 0,  4, "secp128r1"                      }, /* 404 */
- {        0x1D,               406, 0,  4, "secp128r2"                      }, /* 405 */
- {        0x1E,               407, 0,  4, "secp160r2"                      }, /* 406 */
- {        0x1F,               408, 0,  4, "secp192k1"                      }, /* 407 */
- {        0x20,               409, 0,  4, "secp224k1"                      }, /* 408 */
- {        0x21,               410, 0,  4, "secp224r1"                      }, /* 409 */
- {        0x22,               411, 0,  4, "secp384r1"                      }, /* 410 */
- {        0x23,               412, 0,  4, "secp521r1"                      }, /* 411 */
- {        0x24,               413, 0,  4, "sect409k1"                      }, /* 412 */
- {        0x25,               414, 0,  4, "sect409r1"                      }, /* 413 */
- {        0x26,               415, 0,  4, "sect571k1"                      }, /* 414 */
- {        0x27,                 0, 0,  4, "sect571r1"                      }, /* 415 */
- {0x60,                       470, 1,  0, ""                               }, /* 416 */
- {  0x86,                       0, 1,  1, ""                               }, /* 417 */
- {    0x48,                     0, 1,  2, ""                               }, /* 418 */
- {      0x01,                   0, 1,  3, "organization"                   }, /* 419 */
- {        0x65,               446, 1,  4, "gov"                            }, /* 420 */
- {          0x03,               0, 1,  5, "csor"                           }, /* 421 */
- {            0x04,             0, 1,  6, "nistalgorithm"                  }, /* 422 */
- {              0x01,         433, 1,  7, "aes"                            }, /* 423 */
- {                0x02,       425, 0,  8, "id-aes128-CBC"                  }, /* 424 */
- {                0x06,       426, 0,  8, "id-aes128-GCM"                  }, /* 425 */
- {                0x07,       427, 0,  8, "id-aes128-CCM"                  }, /* 426 */
- {                0x16,       428, 0,  8, "id-aes192-CBC"                  }, /* 427 */
- {                0x1A,       429, 0,  8, "id-aes192-GCM"                  }, /* 428 */
- {                0x1B,       430, 0,  8, "id-aes192-CCM"                  }, /* 429 */
- {                0x2A,       431, 0,  8, "id-aes256-CBC"                  }, /* 430 */
- {                0x2E,       432, 0,  8, "id-aes256-GCM"                  }, /* 431 */
- {                0x2F,         0, 0,  8, "id-aes256-CCM"                  }, /* 432 */
- {              0x02,           0, 1,  7, "hashalgs"                       }, /* 433 */
- {                0x01,       435, 0,  8, "id-sha256"                      }, /* 434 */
- {                0x02,       436, 0,  8, "id-sha384"                      }, /* 435 */
- {                0x03,       437, 0,  8, "id-sha512"                      }, /* 436 */
- {                0x04,       438, 0,  8, "id-sha224"                      }, /* 437 */
- {                0x05,       439, 0,  8, "id-sha512-224"                  }, /* 438 */
- {                0x06,       440, 0,  8, "id-sha512-256"                  }, /* 439 */
- {                0x07,       441, 0,  8, "id-sha3-224"                    }, /* 440 */
- {                0x08,       442, 0,  8, "id-sha3-256"                    }, /* 441 */
- {                0x09,       443, 0,  8, "id-sha3-384"                    }, /* 442 */
- {                0x0A,       444, 0,  8, "id-sha3-512"                    }, /* 443 */
- {                0x0B,       445, 0,  8, "id-shake128"                    }, /* 444 */
- {                0x0C,         0, 0,  8, "id-shake256"                    }, /* 445 */
- {        0x86,                 0, 1,  4, ""                               }, /* 446 */
- {          0xf8,               0, 1,  5, ""                               }, /* 447 */
- {            0x42,           460, 1,  6, "netscape"                       }, /* 448 */
- {              0x01,         455, 1,  7, ""                               }, /* 449 */
- {                0x01,       451, 0,  8, "nsCertType"                     }, /* 450 */
- {                0x03,       452, 0,  8, "nsRevocationUrl"                }, /* 451 */
- {                0x04,       453, 0,  8, "nsCaRevocationUrl"              }, /* 452 */
- {                0x08,       454, 0,  8, "nsCaPolicyUrl"                  }, /* 453 */
- {                0x0d,         0, 0,  8, "nsComment"                      }, /* 454 */
- {              0x03,         458, 1,  7, "directory"                      }, /* 455 */
- {                0x01,         0, 1,  8, ""                               }, /* 456 */
- {                  0x03,       0, 0,  9, "employeeNumber"                 }, /* 457 */
- {              0x04,           0, 1,  7, "policy"                         }, /* 458 */
- {                0x01,         0, 0,  8, "nsSGC"                          }, /* 459 */
- {            0x45,             0, 1,  6, "verisign"                       }, /* 460 */
- {              0x01,           0, 1,  7, "pki"                            }, /* 461 */
- {                0x09,         0, 1,  8, "attributes"                     }, /* 462 */
- {                  0x02,     464, 0,  9, "messageType"                    }, /* 463 */
- {                  0x03,     465, 0,  9, "pkiStatus"                      }, /* 464 */
- {                  0x04,     466, 0,  9, "failInfo"                       }, /* 465 */
- {                  0x05,     467, 0,  9, "senderNonce"                    }, /* 466 */
- {                  0x06,     468, 0,  9, "recipientNonce"                 }, /* 467 */
- {                  0x07,     469, 0,  9, "transID"                        }, /* 468 */
- {                  0x08,       0, 0,  9, "extensionReq"                   }, /* 469 */
- {0x67,                         0, 1,  0, ""                               }, /* 470 */
- {  0x81,                       0, 1,  1, ""                               }, /* 471 */
- {    0x05,                     0, 1,  2, ""                               }, /* 472 */
- {      0x02,                   0, 1,  3, "tcg-attribute"                  }, /* 473 */
- {        0x01,               475, 0,  4, "tcg-at-tpmManufacturer"         }, /* 474 */
- {        0x02,               476, 0,  4, "tcg-at-tpmModel"                }, /* 475 */
- {        0x03,               477, 0,  4, "tcg-at-tpmVersion"              }, /* 476 */
- {        0x0F,                 0, 0,  4, "tcg-at-tpmIdLabel"              }  /* 477 */
+ {    0x41,                    37, 0,  2, "pseudonym"                      }, /*  36 */
+ {    0x48,                     0, 0,  2, "role"                           }, /*  37 */
+ {  0x1D,                       0, 1,  1, "id-ce"                          }, /*  38 */
+ {    0x09,                    40, 0,  2, "subjectDirectoryAttrs"          }, /*  39 */
+ {    0x0E,                    41, 0,  2, "subjectKeyIdentifier"           }, /*  40 */
+ {    0x0F,                    42, 0,  2, "keyUsage"                       }, /*  41 */
+ {    0x10,                    43, 0,  2, "privateKeyUsagePeriod"          }, /*  42 */
+ {    0x11,                    44, 0,  2, "subjectAltName"                 }, /*  43 */
+ {    0x12,                    45, 0,  2, "issuerAltName"                  }, /*  44 */
+ {    0x13,                    46, 0,  2, "basicConstraints"               }, /*  45 */
+ {    0x14,                    47, 0,  2, "crlNumber"                      }, /*  46 */
+ {    0x15,                    48, 0,  2, "reasonCode"                     }, /*  47 */
+ {    0x17,                    49, 0,  2, "holdInstructionCode"            }, /*  48 */
+ {    0x18,                    50, 0,  2, "invalidityDate"                 }, /*  49 */
+ {    0x1B,                    51, 0,  2, "deltaCrlIndicator"              }, /*  50 */
+ {    0x1C,                    52, 0,  2, "issuingDistributionPoint"       }, /*  51 */
+ {    0x1D,                    53, 0,  2, "certificateIssuer"              }, /*  52 */
+ {    0x1E,                    54, 0,  2, "nameConstraints"                }, /*  53 */
+ {    0x1F,                    55, 0,  2, "crlDistributionPoints"          }, /*  54 */
+ {    0x20,                    57, 1,  2, "certificatePolicies"            }, /*  55 */
+ {      0x00,                   0, 0,  3, "anyPolicy"                      }, /*  56 */
+ {    0x21,                    58, 0,  2, "policyMappings"                 }, /*  57 */
+ {    0x23,                    59, 0,  2, "authorityKeyIdentifier"         }, /*  58 */
+ {    0x24,                    60, 0,  2, "policyConstraints"              }, /*  59 */
+ {    0x25,                    62, 1,  2, "extendedKeyUsage"               }, /*  60 */
+ {      0x00,                   0, 0,  3, "anyExtendedKeyUsage"            }, /*  61 */
+ {    0x2E,                    63, 0,  2, "freshestCRL"                    }, /*  62 */
+ {    0x36,                    64, 0,  2, "inhibitAnyPolicy"               }, /*  63 */
+ {    0x37,                    65, 0,  2, "targetInformation"              }, /*  64 */
+ {    0x38,                     0, 0,  2, "noRevAvail"                     }, /*  65 */
+ {0x2A,                       190, 1,  0, ""                               }, /*  66 */
+ {  0x83,                      79, 1,  1, ""                               }, /*  67 */
+ {    0x08,                     0, 1,  2, "jp"                             }, /*  68 */
+ {      0x8C,                   0, 1,  3, ""                               }, /*  69 */
+ {        0x9A,                 0, 1,  4, ""                               }, /*  70 */
+ {          0x4B,               0, 1,  5, ""                               }, /*  71 */
+ {            0x3D,             0, 1,  6, ""                               }, /*  72 */
+ {              0x01,           0, 1,  7, "security"                       }, /*  73 */
+ {                0x01,         0, 1,  8, "algorithm"                      }, /*  74 */
+ {                  0x01,       0, 1,  9, "symm-encryption-alg"            }, /*  75 */
+ {                    0x02,    77, 0, 10, "camellia128-cbc"                }, /*  76 */
+ {                    0x03,    78, 0, 10, "camellia192-cbc"                }, /*  77 */
+ {                    0x04,     0, 0, 10, "camellia256-cbc"                }, /*  78 */
+ {  0x86,                       0, 1,  1, ""                               }, /*  79 */
+ {    0x48,                     0, 1,  2, "us"                             }, /*  80 */
+ {      0x86,                 149, 1,  3, ""                               }, /*  81 */
+ {        0xF6,                87, 1,  4, ""                               }, /*  82 */
+ {          0x7D,               0, 1,  5, "NortelNetworks"                 }, /*  83 */
+ {            0x07,             0, 1,  6, "Entrust"                        }, /*  84 */
+ {              0x41,           0, 1,  7, "nsn-ce"                         }, /*  85 */
+ {                0x00,         0, 0,  8, "entrustVersInfo"                }, /*  86 */
+ {        0xF7,                 0, 1,  4, ""                               }, /*  87 */
+ {          0x0D,               0, 1,  5, "RSADSI"                         }, /*  88 */
+ {            0x01,           144, 1,  6, "PKCS"                           }, /*  89 */
+ {              0x01,         102, 1,  7, "PKCS-1"                         }, /*  90 */
+ {                0x01,        92, 0,  8, "rsaEncryption"                  }, /*  91 */
+ {                0x02,        93, 0,  8, "md2WithRSAEncryption"           }, /*  92 */
+ {                0x04,        94, 0,  8, "md5WithRSAEncryption"           }, /*  93 */
+ {                0x05,        95, 0,  8, "sha-1WithRSAEncryption"         }, /*  94 */
+ {                0x07,        96, 0,  8, "id-RSAES-OAEP"                  }, /*  95 */
+ {                0x08,        97, 0,  8, "id-mgf1"                        }, /*  96 */
+ {                0x09,        98, 0,  8, "id-pSpecified"                  }, /*  97 */
+ {                0x0B,        99, 0,  8, "sha256WithRSAEncryption"        }, /*  98 */
+ {                0x0C,       100, 0,  8, "sha384WithRSAEncryption"        }, /*  99 */
+ {                0x0D,       101, 0,  8, "sha512WithRSAEncryption"        }, /* 100 */
+ {                0x0E,         0, 0,  8, "sha224WithRSAEncryption"        }, /* 101 */
+ {              0x05,         107, 1,  7, "PKCS-5"                         }, /* 102 */
+ {                0x03,       104, 0,  8, "pbeWithMD5AndDES-CBC"           }, /* 103 */
+ {                0x0A,       105, 0,  8, "pbeWithSHA1AndDES-CBC"          }, /* 104 */
+ {                0x0C,       106, 0,  8, "id-PBKDF2"                      }, /* 105 */
+ {                0x0D,         0, 0,  8, "id-PBES2"                       }, /* 106 */
+ {              0x07,         114, 1,  7, "PKCS-7"                         }, /* 107 */
+ {                0x01,       109, 0,  8, "data"                           }, /* 108 */
+ {                0x02,       110, 0,  8, "signedData"                     }, /* 109 */
+ {                0x03,       111, 0,  8, "envelopedData"                  }, /* 110 */
+ {                0x04,       112, 0,  8, "signedAndEnvelopedData"         }, /* 111 */
+ {                0x05,       113, 0,  8, "digestedData"                   }, /* 112 */
+ {                0x06,         0, 0,  8, "encryptedData"                  }, /* 113 */
+ {              0x09,         128, 1,  7, "PKCS-9"                         }, /* 114 */
+ {                0x01,       116, 0,  8, "E"                              }, /* 115 */
+ {                0x02,       117, 0,  8, "unstructuredName"               }, /* 116 */
+ {                0x03,       118, 0,  8, "contentType"                    }, /* 117 */
+ {                0x04,       119, 0,  8, "messageDigest"                  }, /* 118 */
+ {                0x05,       120, 0,  8, "signingTime"                    }, /* 119 */
+ {                0x06,       121, 0,  8, "counterSignature"               }, /* 120 */
+ {                0x07,       122, 0,  8, "challengePassword"              }, /* 121 */
+ {                0x08,       123, 0,  8, "unstructuredAddress"            }, /* 122 */
+ {                0x0E,       124, 0,  8, "extensionRequest"               }, /* 123 */
+ {                0x0F,       125, 0,  8, "S/MIME Capabilities"            }, /* 124 */
+ {                0x16,         0, 1,  8, "certTypes"                      }, /* 125 */
+ {                  0x01,     127, 0,  9, "X.509"                          }, /* 126 */
+ {                  0x02,       0, 0,  9, "SDSI"                           }, /* 127 */
+ {              0x0c,           0, 1,  7, "PKCS-12"                        }, /* 128 */
+ {                0x01,       136, 1,  8, "pbeIds"                         }, /* 129 */
+ {                  0x01,     131, 0,  9, "pbeWithSHAAnd128BitRC4"         }, /* 130 */
+ {                  0x02,     132, 0,  9, "pbeWithSHAAnd40BitRC4"          }, /* 131 */
+ {                  0x03,     133, 0,  9, "pbeWithSHAAnd3-KeyTripleDES-CBC"}, /* 132 */
+ {                  0x04,     134, 0,  9, "pbeWithSHAAnd2-KeyTripleDES-CBC"}, /* 133 */
+ {                  0x05,     135, 0,  9, "pbeWithSHAAnd128BitRC2-CBC"     }, /* 134 */
+ {                  0x06,       0, 0,  9, "pbeWithSHAAnd40BitRC2-CBC"      }, /* 135 */
+ {                0x0a,         0, 1,  8, "PKCS-12v1"                      }, /* 136 */
+ {                  0x01,       0, 1,  9, "bagIds"                         }, /* 137 */
+ {                    0x01,   139, 0, 10, "keyBag"                         }, /* 138 */
+ {                    0x02,   140, 0, 10, "pkcs8ShroudedKeyBag"            }, /* 139 */
+ {                    0x03,   141, 0, 10, "certBag"                        }, /* 140 */
+ {                    0x04,   142, 0, 10, "crlBag"                         }, /* 141 */
+ {                    0x05,   143, 0, 10, "secretBag"                      }, /* 142 */
+ {                    0x06,     0, 0, 10, "safeContentsBag"                }, /* 143 */
+ {            0x02,           147, 1,  6, "digestAlgorithm"                }, /* 144 */
+ {              0x02,         146, 0,  7, "md2"                            }, /* 145 */
+ {              0x05,           0, 0,  7, "md5"                            }, /* 146 */
+ {            0x03,             0, 1,  6, "encryptionAlgorithm"            }, /* 147 */
+ {              0x07,           0, 0,  7, "3des-ede-cbc"                   }, /* 148 */
+ {      0xCE,                   0, 1,  3, ""                               }, /* 149 */
+ {        0x3D,                 0, 1,  4, "ansi-X9-62"                     }, /* 150 */
+ {          0x02,             153, 1,  5, "id-publicKeyType"               }, /* 151 */
+ {            0x01,             0, 0,  6, "id-ecPublicKey"                 }, /* 152 */
+ {          0x03,             183, 1,  5, "ellipticCurve"                  }, /* 153 */
+ {            0x00,           175, 1,  6, "c-TwoCurve"                     }, /* 154 */
+ {              0x01,         156, 0,  7, "c2pnb163v1"                     }, /* 155 */
+ {              0x02,         157, 0,  7, "c2pnb163v2"                     }, /* 156 */
+ {              0x03,         158, 0,  7, "c2pnb163v3"                     }, /* 157 */
+ {              0x04,         159, 0,  7, "c2pnb176w1"                     }, /* 158 */
+ {              0x05,         160, 0,  7, "c2tnb191v1"                     }, /* 159 */
+ {              0x06,         161, 0,  7, "c2tnb191v2"                     }, /* 160 */
+ {              0x07,         162, 0,  7, "c2tnb191v3"                     }, /* 161 */
+ {              0x08,         163, 0,  7, "c2onb191v4"                     }, /* 162 */
+ {              0x09,         164, 0,  7, "c2onb191v5"                     }, /* 163 */
+ {              0x0A,         165, 0,  7, "c2pnb208w1"                     }, /* 164 */
+ {              0x0B,         166, 0,  7, "c2tnb239v1"                     }, /* 165 */
+ {              0x0C,         167, 0,  7, "c2tnb239v2"                     }, /* 166 */
+ {              0x0D,         168, 0,  7, "c2tnb239v3"                     }, /* 167 */
+ {              0x0E,         169, 0,  7, "c2onb239v4"                     }, /* 168 */
+ {              0x0F,         170, 0,  7, "c2onb239v5"                     }, /* 169 */
+ {              0x10,         171, 0,  7, "c2pnb272w1"                     }, /* 170 */
+ {              0x11,         172, 0,  7, "c2pnb304w1"                     }, /* 171 */
+ {              0x12,         173, 0,  7, "c2tnb359v1"                     }, /* 172 */
+ {              0x13,         174, 0,  7, "c2pnb368w1"                     }, /* 173 */
+ {              0x14,           0, 0,  7, "c2tnb431r1"                     }, /* 174 */
+ {            0x01,             0, 1,  6, "primeCurve"                     }, /* 175 */
+ {              0x01,         177, 0,  7, "prime192v1"                     }, /* 176 */
+ {              0x02,         178, 0,  7, "prime192v2"                     }, /* 177 */
+ {              0x03,         179, 0,  7, "prime192v3"                     }, /* 178 */
+ {              0x04,         180, 0,  7, "prime239v1"                     }, /* 179 */
+ {              0x05,         181, 0,  7, "prime239v2"                     }, /* 180 */
+ {              0x06,         182, 0,  7, "prime239v3"                     }, /* 181 */
+ {              0x07,           0, 0,  7, "prime256v1"                     }, /* 182 */
+ {          0x04,               0, 1,  5, "id-ecSigType"                   }, /* 183 */
+ {            0x01,           185, 0,  6, "ecdsa-with-SHA1"                }, /* 184 */
+ {            0x03,             0, 1,  6, "ecdsa-with-Specified"           }, /* 185 */
+ {              0x01,         187, 0,  7, "ecdsa-with-SHA224"              }, /* 186 */
+ {              0x02,         188, 0,  7, "ecdsa-with-SHA256"              }, /* 187 */
+ {              0x03,         189, 0,  7, "ecdsa-with-SHA384"              }, /* 188 */
+ {              0x04,           0, 0,  7, "ecdsa-with-SHA512"              }, /* 189 */
+ {0x2B,                       417, 1,  0, ""                               }, /* 190 */
+ {  0x06,                     331, 1,  1, "dod"                            }, /* 191 */
+ {    0x01,                     0, 1,  2, "internet"                       }, /* 192 */
+ {      0x04,                 282, 1,  3, "private"                        }, /* 193 */
+ {        0x01,                 0, 1,  4, "enterprise"                     }, /* 194 */
+ {          0x82,             232, 1,  5, ""                               }, /* 195 */
+ {            0x37,           208, 1,  6, "Microsoft"                      }, /* 196 */
+ {              0x0A,         201, 1,  7, ""                               }, /* 197 */
+ {                0x03,         0, 1,  8, ""                               }, /* 198 */
+ {                  0x03,     200, 0,  9, "msSGC"                          }, /* 199 */
+ {                  0x04,       0, 0,  9, "msEncryptingFileSystem"         }, /* 200 */
+ {              0x14,         205, 1,  7, "msEnrollmentInfrastructure"     }, /* 201 */
+ {                0x02,         0, 1,  8, "msCertificateTypeExtension"     }, /* 202 */
+ {                  0x02,     204, 0,  9, "msSmartcardLogon"               }, /* 203 */
+ {                  0x03,       0, 0,  9, "msUPN"                          }, /* 204 */
+ {              0x15,           0, 1,  7, "msCertSrvInfrastructure"        }, /* 205 */
+ {                0x07,       207, 0,  8, "msCertTemplate"                 }, /* 206 */
+ {                0x0A,         0, 0,  8, "msApplicationCertPolicies"      }, /* 207 */
+ {            0xA0,             0, 1,  6, ""                               }, /* 208 */
+ {              0x2A,           0, 1,  7, "ITA"                            }, /* 209 */
+ {                0x01,       211, 0,  8, "strongSwan"                     }, /* 210 */
+ {                0x02,       212, 0,  8, "cps"                            }, /* 211 */
+ {                0x03,       213, 0,  8, "e-voting"                       }, /* 212 */
+ {                0x05,         0, 1,  8, "BLISS"                          }, /* 213 */
+ {                  0x01,     216, 1,  9, "keyType"                        }, /* 214 */
+ {                    0x01,     0, 0, 10, "blissPublicKey"                 }, /* 215 */
+ {                  0x02,     225, 1,  9, "parameters"                     }, /* 216 */
+ {                    0x01,   218, 0, 10, "BLISS-I"                        }, /* 217 */
+ {                    0x02,   219, 0, 10, "BLISS-II"                       }, /* 218 */
+ {                    0x03,   220, 0, 10, "BLISS-III"                      }, /* 219 */
+ {                    0x04,   221, 0, 10, "BLISS-IV"                       }, /* 220 */
+ {                    0x05,   222, 0, 10, "BLISS-B-I"                      }, /* 221 */
+ {                    0x06,   223, 0, 10, "BLISS-B-II"                     }, /* 222 */
+ {                    0x07,   224, 0, 10, "BLISS-B-III"                    }, /* 223 */
+ {                    0x08,     0, 0, 10, "BLISS-B-IV"                     }, /* 224 */
+ {                  0x03,       0, 1,  9, "blissSigType"                   }, /* 225 */
+ {                    0x01,   227, 0, 10, "BLISS-with-SHA2-512"            }, /* 226 */
+ {                    0x02,   228, 0, 10, "BLISS-with-SHA2-384"            }, /* 227 */
+ {                    0x03,   229, 0, 10, "BLISS-with-SHA2-256"            }, /* 228 */
+ {                    0x04,   230, 0, 10, "BLISS-with-SHA3-512"            }, /* 229 */
+ {                    0x05,   231, 0, 10, "BLISS-with-SHA3-384"            }, /* 230 */
+ {                    0x06,     0, 0, 10, "BLISS-with-SHA3-256"            }, /* 231 */
+ {          0x89,             239, 1,  5, ""                               }, /* 232 */
+ {            0x31,             0, 1,  6, ""                               }, /* 233 */
+ {              0x01,           0, 1,  7, ""                               }, /* 234 */
+ {                0x01,         0, 1,  8, ""                               }, /* 235 */
+ {                  0x02,       0, 1,  9, ""                               }, /* 236 */
+ {                    0x02,     0, 1, 10, ""                               }, /* 237 */
+ {                      0x4B,   0, 0, 11, "TCGID"                          }, /* 238 */
+ {          0x97,             243, 1,  5, ""                               }, /* 239 */
+ {            0x55,             0, 1,  6, ""                               }, /* 240 */
+ {              0x01,           0, 1,  7, ""                               }, /* 241 */
+ {                0x02,         0, 0,  8, "blowfish-cbc"                   }, /* 242 */
+ {          0xC1,               0, 1,  5, ""                               }, /* 243 */
+ {            0x16,             0, 1,  6, "ntruCryptosystems"              }, /* 244 */
+ {              0x01,           0, 1,  7, "eess"                           }, /* 245 */
+ {                0x01,         0, 1,  8, "eess1"                          }, /* 246 */
+ {                  0x01,     251, 1,  9, "eess1-algs"                     }, /* 247 */
+ {                    0x01,   249, 0, 10, "ntru-EESS1v1-SVES"              }, /* 248 */
+ {                    0x02,   250, 0, 10, "ntru-EESS1v1-SVSSA"             }, /* 249 */
+ {                    0x03,     0, 0, 10, "ntru-EESS1v1-NTRUSign"          }, /* 250 */
+ {                  0x02,     281, 1,  9, "eess1-params"                   }, /* 251 */
+ {                    0x01,   253, 0, 10, "ees251ep1"                      }, /* 252 */
+ {                    0x02,   254, 0, 10, "ees347ep1"                      }, /* 253 */
+ {                    0x03,   255, 0, 10, "ees503ep1"                      }, /* 254 */
+ {                    0x07,   256, 0, 10, "ees251sp2"                      }, /* 255 */
+ {                    0x0C,   257, 0, 10, "ees251ep4"                      }, /* 256 */
+ {                    0x0D,   258, 0, 10, "ees251ep5"                      }, /* 257 */
+ {                    0x0E,   259, 0, 10, "ees251sp3"                      }, /* 258 */
+ {                    0x0F,   260, 0, 10, "ees251sp4"                      }, /* 259 */
+ {                    0x10,   261, 0, 10, "ees251sp5"                      }, /* 260 */
+ {                    0x11,   262, 0, 10, "ees251sp6"                      }, /* 261 */
+ {                    0x12,   263, 0, 10, "ees251sp7"                      }, /* 262 */
+ {                    0x13,   264, 0, 10, "ees251sp8"                      }, /* 263 */
+ {                    0x14,   265, 0, 10, "ees251sp9"                      }, /* 264 */
+ {                    0x22,   266, 0, 10, "ees401ep1"                      }, /* 265 */
+ {                    0x23,   267, 0, 10, "ees449ep1"                      }, /* 266 */
+ {                    0x24,   268, 0, 10, "ees677ep1"                      }, /* 267 */
+ {                    0x25,   269, 0, 10, "ees1087ep2"                     }, /* 268 */
+ {                    0x26,   270, 0, 10, "ees541ep1"                      }, /* 269 */
+ {                    0x27,   271, 0, 10, "ees613ep1"                      }, /* 270 */
+ {                    0x28,   272, 0, 10, "ees887ep1"                      }, /* 271 */
+ {                    0x29,   273, 0, 10, "ees1171ep1"                     }, /* 272 */
+ {                    0x2A,   274, 0, 10, "ees659ep1"                      }, /* 273 */
+ {                    0x2B,   275, 0, 10, "ees761ep1"                      }, /* 274 */
+ {                    0x2C,   276, 0, 10, "ees1087ep1"                     }, /* 275 */
+ {                    0x2D,   277, 0, 10, "ees1499ep1"                     }, /* 276 */
+ {                    0x2E,   278, 0, 10, "ees401ep2"                      }, /* 277 */
+ {                    0x2F,   279, 0, 10, "ees439ep1"                      }, /* 278 */
+ {                    0x30,   280, 0, 10, "ees593ep1"                      }, /* 279 */
+ {                    0x31,     0, 0, 10, "ees743ep1"                      }, /* 280 */
+ {                  0x03,       0, 0,  9, "eess1-encodingMethods"          }, /* 281 */
+ {      0x05,                   0, 1,  3, "security"                       }, /* 282 */
+ {        0x05,                 0, 1,  4, "mechanisms"                     }, /* 283 */
+ {          0x07,             328, 1,  5, "id-pkix"                        }, /* 284 */
+ {            0x01,           289, 1,  6, "id-pe"                          }, /* 285 */
+ {              0x01,         287, 0,  7, "authorityInfoAccess"            }, /* 286 */
+ {              0x03,         288, 0,  7, "qcStatements"                   }, /* 287 */
+ {              0x07,           0, 0,  7, "ipAddrBlocks"                   }, /* 288 */
+ {            0x02,           292, 1,  6, "id-qt"                          }, /* 289 */
+ {              0x01,         291, 0,  7, "cps"                            }, /* 290 */
+ {              0x02,           0, 0,  7, "unotice"                        }, /* 291 */
+ {            0x03,           302, 1,  6, "id-kp"                          }, /* 292 */
+ {              0x01,         294, 0,  7, "serverAuth"                     }, /* 293 */
+ {              0x02,         295, 0,  7, "clientAuth"                     }, /* 294 */
+ {              0x03,         296, 0,  7, "codeSigning"                    }, /* 295 */
+ {              0x04,         297, 0,  7, "emailProtection"                }, /* 296 */
+ {              0x05,         298, 0,  7, "ipsecEndSystem"                 }, /* 297 */
+ {              0x06,         299, 0,  7, "ipsecTunnel"                    }, /* 298 */
+ {              0x07,         300, 0,  7, "ipsecUser"                      }, /* 299 */
+ {              0x08,         301, 0,  7, "timeStamping"                   }, /* 300 */
+ {              0x09,           0, 0,  7, "ocspSigning"                    }, /* 301 */
+ {            0x08,           310, 1,  6, "id-otherNames"                  }, /* 302 */
+ {              0x01,         304, 0,  7, "personalData"                   }, /* 303 */
+ {              0x02,         305, 0,  7, "userGroup"                      }, /* 304 */
+ {              0x03,         306, 0,  7, "id-on-permanentIdentifier"      }, /* 305 */
+ {              0x04,         307, 0,  7, "id-on-hardwareModuleName"       }, /* 306 */
+ {              0x05,         308, 0,  7, "xmppAddr"                       }, /* 307 */
+ {              0x06,         309, 0,  7, "id-on-SIM"                      }, /* 308 */
+ {              0x07,           0, 0,  7, "id-on-dnsSRV"                   }, /* 309 */
+ {            0x0A,           315, 1,  6, "id-aca"                         }, /* 310 */
+ {              0x01,         312, 0,  7, "authenticationInfo"             }, /* 311 */
+ {              0x02,         313, 0,  7, "accessIdentity"                 }, /* 312 */
+ {              0x03,         314, 0,  7, "chargingIdentity"               }, /* 313 */
+ {              0x04,           0, 0,  7, "group"                          }, /* 314 */
+ {            0x0B,           316, 0,  6, "subjectInfoAccess"              }, /* 315 */
+ {            0x30,             0, 1,  6, "id-ad"                          }, /* 316 */
+ {              0x01,         325, 1,  7, "ocsp"                           }, /* 317 */
+ {                0x01,       319, 0,  8, "basic"                          }, /* 318 */
+ {                0x02,       320, 0,  8, "nonce"                          }, /* 319 */
+ {                0x03,       321, 0,  8, "crl"                            }, /* 320 */
+ {                0x04,       322, 0,  8, "response"                       }, /* 321 */
+ {                0x05,       323, 0,  8, "noCheck"                        }, /* 322 */
+ {                0x06,       324, 0,  8, "archiveCutoff"                  }, /* 323 */
+ {                0x07,         0, 0,  8, "serviceLocator"                 }, /* 324 */
+ {              0x02,         326, 0,  7, "caIssuers"                      }, /* 325 */
+ {              0x03,         327, 0,  7, "timeStamping"                   }, /* 326 */
+ {              0x05,           0, 0,  7, "caRepository"                   }, /* 327 */
+ {          0x08,               0, 1,  5, "ipsec"                          }, /* 328 */
+ {            0x02,             0, 1,  6, "certificate"                    }, /* 329 */
+ {              0x02,           0, 0,  7, "iKEIntermediate"                }, /* 330 */
+ {  0x0E,                     337, 1,  1, "oiw"                            }, /* 331 */
+ {    0x03,                     0, 1,  2, "secsig"                         }, /* 332 */
+ {      0x02,                   0, 1,  3, "algorithms"                     }, /* 333 */
+ {        0x07,               335, 0,  4, "des-cbc"                        }, /* 334 */
+ {        0x1A,               336, 0,  4, "sha-1"                          }, /* 335 */
+ {        0x1D,                 0, 0,  4, "sha-1WithRSASignature"          }, /* 336 */
+ {  0x24,                     383, 1,  1, "TeleTrusT"                      }, /* 337 */
+ {    0x03,                     0, 1,  2, "algorithm"                      }, /* 338 */
+ {      0x03,                   0, 1,  3, "signatureAlgorithm"             }, /* 339 */
+ {        0x01,               344, 1,  4, "rsaSignature"                   }, /* 340 */
+ {          0x02,             342, 0,  5, "rsaSigWithripemd160"            }, /* 341 */
+ {          0x03,             343, 0,  5, "rsaSigWithripemd128"            }, /* 342 */
+ {          0x04,               0, 0,  5, "rsaSigWithripemd256"            }, /* 343 */
+ {        0x02,                 0, 1,  4, "ecSign"                         }, /* 344 */
+ {          0x01,             346, 0,  5, "ecSignWithsha1"                 }, /* 345 */
+ {          0x02,             347, 0,  5, "ecSignWithripemd160"            }, /* 346 */
+ {          0x03,             348, 0,  5, "ecSignWithmd2"                  }, /* 347 */
+ {          0x04,             349, 0,  5, "ecSignWithmd5"                  }, /* 348 */
+ {          0x05,             366, 1,  5, "ttt-ecg"                        }, /* 349 */
+ {            0x01,           354, 1,  6, "fieldType"                      }, /* 350 */
+ {              0x01,           0, 1,  7, "characteristictwoField"         }, /* 351 */
+ {                0x01,         0, 1,  8, "basisType"                      }, /* 352 */
+ {                  0x01,       0, 0,  9, "ipBasis"                        }, /* 353 */
+ {            0x02,           356, 1,  6, "keyType"                        }, /* 354 */
+ {              0x01,           0, 0,  7, "ecgPublicKey"                   }, /* 355 */
+ {            0x03,           357, 0,  6, "curve"                          }, /* 356 */
+ {            0x04,           364, 1,  6, "signatures"                     }, /* 357 */
+ {              0x01,         359, 0,  7, "ecgdsa-with-RIPEMD160"          }, /* 358 */
+ {              0x02,         360, 0,  7, "ecgdsa-with-SHA1"               }, /* 359 */
+ {              0x03,         361, 0,  7, "ecgdsa-with-SHA224"             }, /* 360 */
+ {              0x04,         362, 0,  7, "ecgdsa-with-SHA256"             }, /* 361 */
+ {              0x05,         363, 0,  7, "ecgdsa-with-SHA384"             }, /* 362 */
+ {              0x06,           0, 0,  7, "ecgdsa-with-SHA512"             }, /* 363 */
+ {            0x05,             0, 1,  6, "module"                         }, /* 364 */
+ {              0x01,           0, 0,  7, "1"                              }, /* 365 */
+ {          0x08,               0, 1,  5, "ecStdCurvesAndGeneration"       }, /* 366 */
+ {            0x01,             0, 1,  6, "ellipticCurve"                  }, /* 367 */
+ {              0x01,           0, 1,  7, "versionOne"                     }, /* 368 */
+ {                0x01,       370, 0,  8, "brainpoolP160r1"                }, /* 369 */
+ {                0x02,       371, 0,  8, "brainpoolP160t1"                }, /* 370 */
+ {                0x03,       372, 0,  8, "brainpoolP192r1"                }, /* 371 */
+ {                0x04,       373, 0,  8, "brainpoolP192t1"                }, /* 372 */
+ {                0x05,       374, 0,  8, "brainpoolP224r1"                }, /* 373 */
+ {                0x06,       375, 0,  8, "brainpoolP224t1"                }, /* 374 */
+ {                0x07,       376, 0,  8, "brainpoolP256r1"                }, /* 375 */
+ {                0x08,       377, 0,  8, "brainpoolP256t1"                }, /* 376 */
+ {                0x09,       378, 0,  8, "brainpoolP320r1"                }, /* 377 */
+ {                0x0A,       379, 0,  8, "brainpoolP320t1"                }, /* 378 */
+ {                0x0B,       380, 0,  8, "brainpoolP384r1"                }, /* 379 */
+ {                0x0C,       381, 0,  8, "brainpoolP384t1"                }, /* 380 */
+ {                0x0D,       382, 0,  8, "brainpoolP512r1"                }, /* 381 */
+ {                0x0E,         0, 0,  8, "brainpoolP512t1"                }, /* 382 */
+ {  0x81,                       0, 1,  1, ""                               }, /* 383 */
+ {    0x04,                     0, 1,  2, "Certicom"                       }, /* 384 */
+ {      0x00,                   0, 1,  3, "curve"                          }, /* 385 */
+ {        0x01,               387, 0,  4, "sect163k1"                      }, /* 386 */
+ {        0x02,               388, 0,  4, "sect163r1"                      }, /* 387 */
+ {        0x03,               389, 0,  4, "sect239k1"                      }, /* 388 */
+ {        0x04,               390, 0,  4, "sect113r1"                      }, /* 389 */
+ {        0x05,               391, 0,  4, "sect113r2"                      }, /* 390 */
+ {        0x06,               392, 0,  4, "secp112r1"                      }, /* 391 */
+ {        0x07,               393, 0,  4, "secp112r2"                      }, /* 392 */
+ {        0x08,               394, 0,  4, "secp160r1"                      }, /* 393 */
+ {        0x09,               395, 0,  4, "secp160k1"                      }, /* 394 */
+ {        0x0A,               396, 0,  4, "secp256k1"                      }, /* 395 */
+ {        0x0F,               397, 0,  4, "sect163r2"                      }, /* 396 */
+ {        0x10,               398, 0,  4, "sect283k1"                      }, /* 397 */
+ {        0x11,               399, 0,  4, "sect283r1"                      }, /* 398 */
+ {        0x16,               400, 0,  4, "sect131r1"                      }, /* 399 */
+ {        0x17,               401, 0,  4, "sect131r2"                      }, /* 400 */
+ {        0x18,               402, 0,  4, "sect193r1"                      }, /* 401 */
+ {        0x19,               403, 0,  4, "sect193r2"                      }, /* 402 */
+ {        0x1A,               404, 0,  4, "sect233k1"                      }, /* 403 */
+ {        0x1B,               405, 0,  4, "sect233r1"                      }, /* 404 */
+ {        0x1C,               406, 0,  4, "secp128r1"                      }, /* 405 */
+ {        0x1D,               407, 0,  4, "secp128r2"                      }, /* 406 */
+ {        0x1E,               408, 0,  4, "secp160r2"                      }, /* 407 */
+ {        0x1F,               409, 0,  4, "secp192k1"                      }, /* 408 */
+ {        0x20,               410, 0,  4, "secp224k1"                      }, /* 409 */
+ {        0x21,               411, 0,  4, "secp224r1"                      }, /* 410 */
+ {        0x22,               412, 0,  4, "secp384r1"                      }, /* 411 */
+ {        0x23,               413, 0,  4, "secp521r1"                      }, /* 412 */
+ {        0x24,               414, 0,  4, "sect409k1"                      }, /* 413 */
+ {        0x25,               415, 0,  4, "sect409r1"                      }, /* 414 */
+ {        0x26,               416, 0,  4, "sect571k1"                      }, /* 415 */
+ {        0x27,                 0, 0,  4, "sect571r1"                      }, /* 416 */
+ {0x60,                       471, 1,  0, ""                               }, /* 417 */
+ {  0x86,                       0, 1,  1, ""                               }, /* 418 */
+ {    0x48,                     0, 1,  2, ""                               }, /* 419 */
+ {      0x01,                   0, 1,  3, "organization"                   }, /* 420 */
+ {        0x65,               447, 1,  4, "gov"                            }, /* 421 */
+ {          0x03,               0, 1,  5, "csor"                           }, /* 422 */
+ {            0x04,             0, 1,  6, "nistalgorithm"                  }, /* 423 */
+ {              0x01,         434, 1,  7, "aes"                            }, /* 424 */
+ {                0x02,       426, 0,  8, "id-aes128-CBC"                  }, /* 425 */
+ {                0x06,       427, 0,  8, "id-aes128-GCM"                  }, /* 426 */
+ {                0x07,       428, 0,  8, "id-aes128-CCM"                  }, /* 427 */
+ {                0x16,       429, 0,  8, "id-aes192-CBC"                  }, /* 428 */
+ {                0x1A,       430, 0,  8, "id-aes192-GCM"                  }, /* 429 */
+ {                0x1B,       431, 0,  8, "id-aes192-CCM"                  }, /* 430 */
+ {                0x2A,       432, 0,  8, "id-aes256-CBC"                  }, /* 431 */
+ {                0x2E,       433, 0,  8, "id-aes256-GCM"                  }, /* 432 */
+ {                0x2F,         0, 0,  8, "id-aes256-CCM"                  }, /* 433 */
+ {              0x02,           0, 1,  7, "hashalgs"                       }, /* 434 */
+ {                0x01,       436, 0,  8, "id-sha256"                      }, /* 435 */
+ {                0x02,       437, 0,  8, "id-sha384"                      }, /* 436 */
+ {                0x03,       438, 0,  8, "id-sha512"                      }, /* 437 */
+ {                0x04,       439, 0,  8, "id-sha224"                      }, /* 438 */
+ {                0x05,       440, 0,  8, "id-sha512-224"                  }, /* 439 */
+ {                0x06,       441, 0,  8, "id-sha512-256"                  }, /* 440 */
+ {                0x07,       442, 0,  8, "id-sha3-224"                    }, /* 441 */
+ {                0x08,       443, 0,  8, "id-sha3-256"                    }, /* 442 */
+ {                0x09,       444, 0,  8, "id-sha3-384"                    }, /* 443 */
+ {                0x0A,       445, 0,  8, "id-sha3-512"                    }, /* 444 */
+ {                0x0B,       446, 0,  8, "id-shake128"                    }, /* 445 */
+ {                0x0C,         0, 0,  8, "id-shake256"                    }, /* 446 */
+ {        0x86,                 0, 1,  4, ""                               }, /* 447 */
+ {          0xf8,               0, 1,  5, ""                               }, /* 448 */
+ {            0x42,           461, 1,  6, "netscape"                       }, /* 449 */
+ {              0x01,         456, 1,  7, ""                               }, /* 450 */
+ {                0x01,       452, 0,  8, "nsCertType"                     }, /* 451 */
+ {                0x03,       453, 0,  8, "nsRevocationUrl"                }, /* 452 */
+ {                0x04,       454, 0,  8, "nsCaRevocationUrl"              }, /* 453 */
+ {                0x08,       455, 0,  8, "nsCaPolicyUrl"                  }, /* 454 */
+ {                0x0d,         0, 0,  8, "nsComment"                      }, /* 455 */
+ {              0x03,         459, 1,  7, "directory"                      }, /* 456 */
+ {                0x01,         0, 1,  8, ""                               }, /* 457 */
+ {                  0x03,       0, 0,  9, "employeeNumber"                 }, /* 458 */
+ {              0x04,           0, 1,  7, "policy"                         }, /* 459 */
+ {                0x01,         0, 0,  8, "nsSGC"                          }, /* 460 */
+ {            0x45,             0, 1,  6, "verisign"                       }, /* 461 */
+ {              0x01,           0, 1,  7, "pki"                            }, /* 462 */
+ {                0x09,         0, 1,  8, "attributes"                     }, /* 463 */
+ {                  0x02,     465, 0,  9, "messageType"                    }, /* 464 */
+ {                  0x03,     466, 0,  9, "pkiStatus"                      }, /* 465 */
+ {                  0x04,     467, 0,  9, "failInfo"                       }, /* 466 */
+ {                  0x05,     468, 0,  9, "senderNonce"                    }, /* 467 */
+ {                  0x06,     469, 0,  9, "recipientNonce"                 }, /* 468 */
+ {                  0x07,     470, 0,  9, "transID"                        }, /* 469 */
+ {                  0x08,       0, 0,  9, "extensionReq"                   }, /* 470 */
+ {0x67,                         0, 1,  0, ""                               }, /* 471 */
+ {  0x81,                       0, 1,  1, ""                               }, /* 472 */
+ {    0x05,                     0, 1,  2, ""                               }, /* 473 */
+ {      0x02,                   0, 1,  3, "tcg-attribute"                  }, /* 474 */
+ {        0x01,               476, 0,  4, "tcg-at-tpmManufacturer"         }, /* 475 */
+ {        0x02,               477, 0,  4, "tcg-at-tpmModel"                }, /* 476 */
+ {        0x03,               478, 0,  4, "tcg-at-tpmVersion"              }, /* 477 */
+ {        0x0F,                 0, 0,  4, "tcg-at-tpmIdLabel"              }  /* 478 */
 };
diff --git a/src/libstrongswan/asn1/oid.h b/src/libstrongswan/asn1/oid.h
index b9ed08d..1120156 100644
--- a/src/libstrongswan/asn1/oid.h
+++ b/src/libstrongswan/asn1/oid.h
@@ -40,220 +40,221 @@ extern const oid_t oid_names[];
 #define OID_INITIALS						33
 #define OID_UNIQUE_IDENTIFIER				34
 #define OID_DN_QUALIFIER					35
-#define OID_ROLE							36
-#define OID_SUBJECT_KEY_ID					39
-#define OID_KEY_USAGE						40
-#define OID_SUBJECT_ALT_NAME				42
-#define OID_BASIC_CONSTRAINTS				44
-#define OID_CRL_NUMBER						45
-#define OID_CRL_REASON_CODE					46
-#define OID_DELTA_CRL_INDICATOR				49
-#define OID_ISSUING_DIST_POINT				50
-#define OID_NAME_CONSTRAINTS				52
-#define OID_CRL_DISTRIBUTION_POINTS			53
-#define OID_CERTIFICATE_POLICIES			54
-#define OID_ANY_POLICY						55
-#define OID_POLICY_MAPPINGS					56
-#define OID_AUTHORITY_KEY_ID				57
-#define OID_POLICY_CONSTRAINTS				58
-#define OID_EXTENDED_KEY_USAGE				59
-#define OID_FRESHEST_CRL					61
-#define OID_INHIBIT_ANY_POLICY				62
-#define OID_TARGET_INFORMATION				63
-#define OID_NO_REV_AVAIL					64
-#define OID_CAMELLIA128_CBC					75
-#define OID_CAMELLIA192_CBC					76
-#define OID_CAMELLIA256_CBC					77
-#define OID_RSA_ENCRYPTION					90
-#define OID_MD2_WITH_RSA					91
-#define OID_MD5_WITH_RSA					92
-#define OID_SHA1_WITH_RSA					93
-#define OID_RSAES_OAEP						94
-#define OID_SHA256_WITH_RSA					97
-#define OID_SHA384_WITH_RSA					98
-#define OID_SHA512_WITH_RSA					99
-#define OID_SHA224_WITH_RSA					100
-#define OID_PBE_MD5_DES_CBC					102
-#define OID_PBE_SHA1_DES_CBC				103
-#define OID_PBKDF2							104
-#define OID_PBES2							105
-#define OID_PKCS7_DATA						107
-#define OID_PKCS7_SIGNED_DATA				108
-#define OID_PKCS7_ENVELOPED_DATA			109
-#define OID_PKCS7_SIGNED_ENVELOPED_DATA		110
-#define OID_PKCS7_DIGESTED_DATA				111
-#define OID_PKCS7_ENCRYPTED_DATA			112
-#define OID_EMAIL_ADDRESS					114
-#define OID_UNSTRUCTURED_NAME				115
-#define OID_PKCS9_CONTENT_TYPE				116
-#define OID_PKCS9_MESSAGE_DIGEST			117
-#define OID_PKCS9_SIGNING_TIME				118
-#define OID_CHALLENGE_PASSWORD				120
-#define OID_UNSTRUCTURED_ADDRESS			121
-#define OID_EXTENSION_REQUEST				122
-#define OID_X509_CERTIFICATE				125
-#define OID_PBE_SHA1_RC4_128				129
-#define OID_PBE_SHA1_RC4_40					130
-#define OID_PBE_SHA1_3DES_CBC				131
-#define OID_PBE_SHA1_3DES_2KEY_CBC			132
-#define OID_PBE_SHA1_RC2_CBC_128			133
-#define OID_PBE_SHA1_RC2_CBC_40				134
-#define OID_P12_KEY_BAG						137
-#define OID_P12_PKCS8_KEY_BAG				138
-#define OID_P12_CERT_BAG					139
-#define OID_P12_CRL_BAG						140
-#define OID_MD2								144
-#define OID_MD5								145
-#define OID_3DES_EDE_CBC					147
-#define OID_EC_PUBLICKEY					151
-#define OID_C2PNB163V1						154
-#define OID_C2PNB163V2						155
-#define OID_C2PNB163V3						156
-#define OID_C2PNB176W1						157
-#define OID_C2PNB191V1						158
-#define OID_C2PNB191V2						159
-#define OID_C2PNB191V3						160
-#define OID_C2PNB191V4						161
-#define OID_C2PNB191V5						162
-#define OID_C2PNB208W1						163
-#define OID_C2PNB239V1						164
-#define OID_C2PNB239V2						165
-#define OID_C2PNB239V3						166
-#define OID_C2PNB239V4						167
-#define OID_C2PNB239V5						168
-#define OID_C2PNB272W1						169
-#define OID_C2PNB304W1						170
-#define OID_C2PNB359V1						171
-#define OID_C2PNB368W1						172
-#define OID_C2PNB431R1						173
-#define OID_PRIME192V1						175
-#define OID_PRIME192V2						176
-#define OID_PRIME192V3						177
-#define OID_PRIME239V1						178
-#define OID_PRIME239V2						179
-#define OID_PRIME239V3						180
-#define OID_PRIME256V1						181
-#define OID_ECDSA_WITH_SHA1					183
-#define OID_ECDSA_WITH_SHA224				185
-#define OID_ECDSA_WITH_SHA256				186
-#define OID_ECDSA_WITH_SHA384				187
-#define OID_ECDSA_WITH_SHA512				188
-#define OID_MS_SMARTCARD_LOGON				202
-#define OID_USER_PRINCIPAL_NAME				203
-#define OID_STRONGSWAN						209
-#define OID_BLISS_PUBLICKEY					214
-#define OID_BLISS_I							216
-#define OID_BLISS_II						217
-#define OID_BLISS_III						218
-#define OID_BLISS_IV						219
-#define OID_BLISS_B_I						220
-#define OID_BLISS_B_II						221
-#define OID_BLISS_B_III						222
-#define OID_BLISS_B_IV						223
-#define OID_BLISS_WITH_SHA2_512				225
-#define OID_BLISS_WITH_SHA2_384				226
-#define OID_BLISS_WITH_SHA2_256				227
-#define OID_BLISS_WITH_SHA3_512				228
-#define OID_BLISS_WITH_SHA3_384				229
-#define OID_BLISS_WITH_SHA3_256				230
-#define OID_TCGID							237
-#define OID_BLOWFISH_CBC					241
-#define OID_AUTHORITY_INFO_ACCESS			285
-#define OID_IP_ADDR_BLOCKS					287
-#define OID_POLICY_QUALIFIER_CPS			289
-#define OID_POLICY_QUALIFIER_UNOTICE		290
-#define OID_SERVER_AUTH						292
-#define OID_CLIENT_AUTH						293
-#define OID_OCSP_SIGNING					300
-#define OID_XMPP_ADDR						306
-#define OID_AUTHENTICATION_INFO				310
-#define OID_ACCESS_IDENTITY					311
-#define OID_CHARGING_IDENTITY				312
-#define OID_GROUP							313
-#define OID_OCSP							316
-#define OID_BASIC							317
-#define OID_NONCE							318
-#define OID_CRL								319
-#define OID_RESPONSE						320
-#define OID_NO_CHECK						321
-#define OID_ARCHIVE_CUTOFF					322
-#define OID_SERVICE_LOCATOR					323
-#define OID_CA_ISSUERS						324
-#define OID_IKE_INTERMEDIATE				329
-#define OID_DES_CBC							333
-#define OID_SHA1							334
-#define OID_SHA1_WITH_RSA_OIW				335
-#define OID_ECGDSA_PUBKEY					354
-#define OID_ECGDSA_SIG_WITH_RIPEMD160		357
-#define OID_ECGDSA_SIG_WITH_SHA1			358
-#define OID_ECGDSA_SIG_WITH_SHA224			359
-#define OID_ECGDSA_SIG_WITH_SHA256			360
-#define OID_ECGDSA_SIG_WITH_SHA384			361
-#define OID_ECGDSA_SIG_WITH_SHA512			362
-#define OID_SECT163K1						385
-#define OID_SECT163R1						386
-#define OID_SECT239K1						387
-#define OID_SECT113R1						388
-#define OID_SECT113R2						389
-#define OID_SECT112R1						390
-#define OID_SECT112R2						391
-#define OID_SECT160R1						392
-#define OID_SECT160K1						393
-#define OID_SECT256K1						394
-#define OID_SECT163R2						395
-#define OID_SECT283K1						396
-#define OID_SECT283R1						397
-#define OID_SECT131R1						398
-#define OID_SECT131R2						399
-#define OID_SECT193R1						400
-#define OID_SECT193R2						401
-#define OID_SECT233K1						402
-#define OID_SECT233R1						403
-#define OID_SECT128R1						404
-#define OID_SECT128R2						405
-#define OID_SECT160R2						406
-#define OID_SECT192K1						407
-#define OID_SECT224K1						408
-#define OID_SECT224R1						409
-#define OID_SECT384R1						410
-#define OID_SECT521R1						411
-#define OID_SECT409K1						412
-#define OID_SECT409R1						413
-#define OID_SECT571K1						414
-#define OID_SECT571R1						415
-#define OID_AES128_CBC						424
-#define OID_AES128_GCM						425
-#define OID_AES128_CCM						426
-#define OID_AES192_CBC						427
-#define OID_AES192_GCM						428
-#define OID_AES192_CCM						429
-#define OID_AES256_CBC						430
-#define OID_AES256_GCM						431
-#define OID_AES256_CCM						432
-#define OID_SHA256							434
-#define OID_SHA384							435
-#define OID_SHA512							436
-#define OID_SHA224							437
-#define OID_SHA3_224						440
-#define OID_SHA3_256						441
-#define OID_SHA3_384						442
-#define OID_SHA3_512						443
-#define OID_NS_REVOCATION_URL				451
-#define OID_NS_CA_REVOCATION_URL			452
-#define OID_NS_CA_POLICY_URL				453
-#define OID_NS_COMMENT						454
-#define OID_EMPLOYEE_NUMBER					457
-#define OID_PKI_MESSAGE_TYPE				463
-#define OID_PKI_STATUS						464
-#define OID_PKI_FAIL_INFO					465
-#define OID_PKI_SENDER_NONCE				466
-#define OID_PKI_RECIPIENT_NONCE				467
-#define OID_PKI_TRANS_ID					468
-#define OID_TPM_MANUFACTURER				474
-#define OID_TPM_MODEL						475
-#define OID_TPM_VERSION						476
-#define OID_TPM_ID_LABEL					477
+#define OID_PSEUDONYM						36
+#define OID_ROLE							37
+#define OID_SUBJECT_KEY_ID					40
+#define OID_KEY_USAGE						41
+#define OID_SUBJECT_ALT_NAME				43
+#define OID_BASIC_CONSTRAINTS				45
+#define OID_CRL_NUMBER						46
+#define OID_CRL_REASON_CODE					47
+#define OID_DELTA_CRL_INDICATOR				50
+#define OID_ISSUING_DIST_POINT				51
+#define OID_NAME_CONSTRAINTS				53
+#define OID_CRL_DISTRIBUTION_POINTS			54
+#define OID_CERTIFICATE_POLICIES			55
+#define OID_ANY_POLICY						56
+#define OID_POLICY_MAPPINGS					57
+#define OID_AUTHORITY_KEY_ID				58
+#define OID_POLICY_CONSTRAINTS				59
+#define OID_EXTENDED_KEY_USAGE				60
+#define OID_FRESHEST_CRL					62
+#define OID_INHIBIT_ANY_POLICY				63
+#define OID_TARGET_INFORMATION				64
+#define OID_NO_REV_AVAIL					65
+#define OID_CAMELLIA128_CBC					76
+#define OID_CAMELLIA192_CBC					77
+#define OID_CAMELLIA256_CBC					78
+#define OID_RSA_ENCRYPTION					91
+#define OID_MD2_WITH_RSA					92
+#define OID_MD5_WITH_RSA					93
+#define OID_SHA1_WITH_RSA					94
+#define OID_RSAES_OAEP						95
+#define OID_SHA256_WITH_RSA					98
+#define OID_SHA384_WITH_RSA					99
+#define OID_SHA512_WITH_RSA					100
+#define OID_SHA224_WITH_RSA					101
+#define OID_PBE_MD5_DES_CBC					103
+#define OID_PBE_SHA1_DES_CBC				104
+#define OID_PBKDF2							105
+#define OID_PBES2							106
+#define OID_PKCS7_DATA						108
+#define OID_PKCS7_SIGNED_DATA				109
+#define OID_PKCS7_ENVELOPED_DATA			110
+#define OID_PKCS7_SIGNED_ENVELOPED_DATA		111
+#define OID_PKCS7_DIGESTED_DATA				112
+#define OID_PKCS7_ENCRYPTED_DATA			113
+#define OID_EMAIL_ADDRESS					115
+#define OID_UNSTRUCTURED_NAME				116
+#define OID_PKCS9_CONTENT_TYPE				117
+#define OID_PKCS9_MESSAGE_DIGEST			118
+#define OID_PKCS9_SIGNING_TIME				119
+#define OID_CHALLENGE_PASSWORD				121
+#define OID_UNSTRUCTURED_ADDRESS			122
+#define OID_EXTENSION_REQUEST				123
+#define OID_X509_CERTIFICATE				126
+#define OID_PBE_SHA1_RC4_128				130
+#define OID_PBE_SHA1_RC4_40					131
+#define OID_PBE_SHA1_3DES_CBC				132
+#define OID_PBE_SHA1_3DES_2KEY_CBC			133
+#define OID_PBE_SHA1_RC2_CBC_128			134
+#define OID_PBE_SHA1_RC2_CBC_40				135
+#define OID_P12_KEY_BAG						138
+#define OID_P12_PKCS8_KEY_BAG				139
+#define OID_P12_CERT_BAG					140
+#define OID_P12_CRL_BAG						141
+#define OID_MD2								145
+#define OID_MD5								146
+#define OID_3DES_EDE_CBC					148
+#define OID_EC_PUBLICKEY					152
+#define OID_C2PNB163V1						155
+#define OID_C2PNB163V2						156
+#define OID_C2PNB163V3						157
+#define OID_C2PNB176W1						158
+#define OID_C2PNB191V1						159
+#define OID_C2PNB191V2						160
+#define OID_C2PNB191V3						161
+#define OID_C2PNB191V4						162
+#define OID_C2PNB191V5						163
+#define OID_C2PNB208W1						164
+#define OID_C2PNB239V1						165
+#define OID_C2PNB239V2						166
+#define OID_C2PNB239V3						167
+#define OID_C2PNB239V4						168
+#define OID_C2PNB239V5						169
+#define OID_C2PNB272W1						170
+#define OID_C2PNB304W1						171
+#define OID_C2PNB359V1						172
+#define OID_C2PNB368W1						173
+#define OID_C2PNB431R1						174
+#define OID_PRIME192V1						176
+#define OID_PRIME192V2						177
+#define OID_PRIME192V3						178
+#define OID_PRIME239V1						179
+#define OID_PRIME239V2						180
+#define OID_PRIME239V3						181
+#define OID_PRIME256V1						182
+#define OID_ECDSA_WITH_SHA1					184
+#define OID_ECDSA_WITH_SHA224				186
+#define OID_ECDSA_WITH_SHA256				187
+#define OID_ECDSA_WITH_SHA384				188
+#define OID_ECDSA_WITH_SHA512				189
+#define OID_MS_SMARTCARD_LOGON				203
+#define OID_USER_PRINCIPAL_NAME				204
+#define OID_STRONGSWAN						210
+#define OID_BLISS_PUBLICKEY					215
+#define OID_BLISS_I							217
+#define OID_BLISS_II						218
+#define OID_BLISS_III						219
+#define OID_BLISS_IV						220
+#define OID_BLISS_B_I						221
+#define OID_BLISS_B_II						222
+#define OID_BLISS_B_III						223
+#define OID_BLISS_B_IV						224
+#define OID_BLISS_WITH_SHA2_512				226
+#define OID_BLISS_WITH_SHA2_384				227
+#define OID_BLISS_WITH_SHA2_256				228
+#define OID_BLISS_WITH_SHA3_512				229
+#define OID_BLISS_WITH_SHA3_384				230
+#define OID_BLISS_WITH_SHA3_256				231
+#define OID_TCGID							238
+#define OID_BLOWFISH_CBC					242
+#define OID_AUTHORITY_INFO_ACCESS			286
+#define OID_IP_ADDR_BLOCKS					288
+#define OID_POLICY_QUALIFIER_CPS			290
+#define OID_POLICY_QUALIFIER_UNOTICE		291
+#define OID_SERVER_AUTH						293
+#define OID_CLIENT_AUTH						294
+#define OID_OCSP_SIGNING					301
+#define OID_XMPP_ADDR						307
+#define OID_AUTHENTICATION_INFO				311
+#define OID_ACCESS_IDENTITY					312
+#define OID_CHARGING_IDENTITY				313
+#define OID_GROUP							314
+#define OID_OCSP							317
+#define OID_BASIC							318
+#define OID_NONCE							319
+#define OID_CRL								320
+#define OID_RESPONSE						321
+#define OID_NO_CHECK						322
+#define OID_ARCHIVE_CUTOFF					323
+#define OID_SERVICE_LOCATOR					324
+#define OID_CA_ISSUERS						325
+#define OID_IKE_INTERMEDIATE				330
+#define OID_DES_CBC							334
+#define OID_SHA1							335
+#define OID_SHA1_WITH_RSA_OIW				336
+#define OID_ECGDSA_PUBKEY					355
+#define OID_ECGDSA_SIG_WITH_RIPEMD160		358
+#define OID_ECGDSA_SIG_WITH_SHA1			359
+#define OID_ECGDSA_SIG_WITH_SHA224			360
+#define OID_ECGDSA_SIG_WITH_SHA256			361
+#define OID_ECGDSA_SIG_WITH_SHA384			362
+#define OID_ECGDSA_SIG_WITH_SHA512			363
+#define OID_SECT163K1						386
+#define OID_SECT163R1						387
+#define OID_SECT239K1						388
+#define OID_SECT113R1						389
+#define OID_SECT113R2						390
+#define OID_SECT112R1						391
+#define OID_SECT112R2						392
+#define OID_SECT160R1						393
+#define OID_SECT160K1						394
+#define OID_SECT256K1						395
+#define OID_SECT163R2						396
+#define OID_SECT283K1						397
+#define OID_SECT283R1						398
+#define OID_SECT131R1						399
+#define OID_SECT131R2						400
+#define OID_SECT193R1						401
+#define OID_SECT193R2						402
+#define OID_SECT233K1						403
+#define OID_SECT233R1						404
+#define OID_SECT128R1						405
+#define OID_SECT128R2						406
+#define OID_SECT160R2						407
+#define OID_SECT192K1						408
+#define OID_SECT224K1						409
+#define OID_SECT224R1						410
+#define OID_SECT384R1						411
+#define OID_SECT521R1						412
+#define OID_SECT409K1						413
+#define OID_SECT409R1						414
+#define OID_SECT571K1						415
+#define OID_SECT571R1						416
+#define OID_AES128_CBC						425
+#define OID_AES128_GCM						426
+#define OID_AES128_CCM						427
+#define OID_AES192_CBC						428
+#define OID_AES192_GCM						429
+#define OID_AES192_CCM						430
+#define OID_AES256_CBC						431
+#define OID_AES256_GCM						432
+#define OID_AES256_CCM						433
+#define OID_SHA256							435
+#define OID_SHA384							436
+#define OID_SHA512							437
+#define OID_SHA224							438
+#define OID_SHA3_224						441
+#define OID_SHA3_256						442
+#define OID_SHA3_384						443
+#define OID_SHA3_512						444
+#define OID_NS_REVOCATION_URL				452
+#define OID_NS_CA_REVOCATION_URL			453
+#define OID_NS_CA_POLICY_URL				454
+#define OID_NS_COMMENT						455
+#define OID_EMPLOYEE_NUMBER					458
+#define OID_PKI_MESSAGE_TYPE				464
+#define OID_PKI_STATUS						465
+#define OID_PKI_FAIL_INFO					466
+#define OID_PKI_SENDER_NONCE				467
+#define OID_PKI_RECIPIENT_NONCE				468
+#define OID_PKI_TRANS_ID					469
+#define OID_TPM_MANUFACTURER				475
+#define OID_TPM_MODEL						476
+#define OID_TPM_VERSION						477
+#define OID_TPM_ID_LABEL					478
 
-#define OID_MAX								478
+#define OID_MAX								479
 
 #endif /* OID_H_ */
diff --git a/src/libstrongswan/asn1/oid.txt b/src/libstrongswan/asn1/oid.txt
index 64dedcb..b5ec15f 100644
--- a/src/libstrongswan/asn1/oid.txt
+++ b/src/libstrongswan/asn1/oid.txt
@@ -34,6 +34,7 @@
     0x2B                     "I"						OID_INITIALS
     0x2D                     "ID"						OID_UNIQUE_IDENTIFIER
     0x2E                     "dnQualifier"				OID_DN_QUALIFIER
+    0x41                     "pseudonym"				OID_PSEUDONYM
     0x48                     "role"						OID_ROLE
   0x1D                       "id-ce"
     0x09                     "subjectDirectoryAttrs"
diff --git a/src/libstrongswan/collections/array.c b/src/libstrongswan/collections/array.c
index 61c696b..a45a68a 100644
--- a/src/libstrongswan/collections/array.c
+++ b/src/libstrongswan/collections/array.c
@@ -277,6 +277,16 @@ void array_insert_create(array_t **array, int idx, void *ptr)
 	array_insert(*array, idx, ptr);
 }
 
+void array_insert_create_value(array_t **array, u_int esize,
+							   int idx, void *val)
+{
+	if (*array == NULL)
+	{
+		*array = array_create(esize, 0);
+	}
+	array_insert(*array, idx, val);
+}
+
 void array_insert_enumerator(array_t *array, int idx, enumerator_t *enumerator)
 {
 	void *ptr;
diff --git a/src/libstrongswan/collections/array.h b/src/libstrongswan/collections/array.h
index 0659c70..c3be1a1 100644
--- a/src/libstrongswan/collections/array.h
+++ b/src/libstrongswan/collections/array.h
@@ -139,6 +139,21 @@ void array_insert(array_t *array, int idx, void *data);
 void array_insert_create(array_t **array, int idx, void *ptr);
 
 /**
+ * Create a value based array if it does not exist, insert value.
+ *
+ * This is a convenience function to insert a value and implicitly
+ * create a value based array if array is NULL. Array is set the the newly
+ * created array, if any.
+ *
+ * @param array			pointer to array reference, potentially NULL
+ * @param esize			element size of this array
+ * @param idx			index to insert item at
+ * @param val			pointer to value to insert
+ */
+void array_insert_create_value(array_t **array, u_int esize,
+							   int idx, void *val);
+
+/**
  * Insert all items from an enumerator to an array.
  *
  * @param array			array to add items to
diff --git a/src/libstrongswan/collections/linked_list.c b/src/libstrongswan/collections/linked_list.c
index a176e5a..b8fe815 100644
--- a/src/libstrongswan/collections/linked_list.c
+++ b/src/libstrongswan/collections/linked_list.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2011 Tobias Brunner
+ * Copyright (C) 2007-2015 Tobias Brunner
  * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
@@ -433,6 +433,56 @@ METHOD(linked_list_t, clone_offset, linked_list_t*,
 	return clone;
 }
 
+METHOD(linked_list_t, equals_offset, bool,
+	private_linked_list_t *this, linked_list_t *other_pub, size_t offset)
+{
+	private_linked_list_t *other = (private_linked_list_t*)other_pub;
+	element_t *cur_t, *cur_o;
+
+	if (this->count != other->count)
+	{
+		return FALSE;
+	}
+	cur_t = this->first;
+	cur_o = other->first;
+	while (cur_t && cur_o)
+	{
+		bool (**method)(void*,void*) = cur_t->value + offset;
+		if (!(*method)(cur_t->value, cur_o->value))
+		{
+			return FALSE;
+		}
+		cur_t = cur_t->next;
+		cur_o = cur_o->next;
+	}
+	return TRUE;
+}
+
+METHOD(linked_list_t, equals_function, bool,
+	private_linked_list_t *this, linked_list_t *other_pub,
+	bool (*fn)(void*,void*))
+{
+	private_linked_list_t *other = (private_linked_list_t*)other_pub;
+	element_t *cur_t, *cur_o;
+
+	if (this->count != other->count)
+	{
+		return FALSE;
+	}
+	cur_t = this->first;
+	cur_o = other->first;
+	while (cur_t && cur_o)
+	{
+		if (!fn(cur_t->value, cur_o->value))
+		{
+			return FALSE;
+		}
+		cur_t = cur_t->next;
+		cur_o = cur_o->next;
+	}
+	return TRUE;
+}
+
 METHOD(linked_list_t, destroy, void,
 	private_linked_list_t *this)
 {
@@ -503,6 +553,8 @@ linked_list_t *linked_list_create()
 			.invoke_offset = (void*)_invoke_offset,
 			.invoke_function = (void*)_invoke_function,
 			.clone_offset = _clone_offset,
+			.equals_offset = _equals_offset,
+			.equals_function = _equals_function,
 			.destroy = _destroy,
 			.destroy_offset = _destroy_offset,
 			.destroy_function = _destroy_function,
diff --git a/src/libstrongswan/collections/linked_list.h b/src/libstrongswan/collections/linked_list.h
index abc33c1..5edaa07 100644
--- a/src/libstrongswan/collections/linked_list.h
+++ b/src/libstrongswan/collections/linked_list.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2011 Tobias Brunner
+ * Copyright (C) 2007-2015 Tobias Brunner
  * Copyright (C) 2005-2008 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
@@ -218,6 +218,27 @@ struct linked_list_t {
 	linked_list_t *(*clone_offset) (linked_list_t *this, size_t offset);
 
 	/**
+	 * Compare two lists and their objects for equality using the given equals
+	 * method.
+	 *
+	 * @param other		list to compare
+	 * @param offset	offset of the objects equals method
+	 * @return			TRUE if lists and objects are equal, FALSE otherwise
+	 */
+	bool (*equals_offset) (linked_list_t *this, linked_list_t *other,
+						   size_t offset);
+
+	/**
+	 * Compare two lists and their objects for equality using the given function.
+	 *
+	 * @param other		list to compare
+	 * @param function	function to compare the objects
+	 * @return			TRUE if lists and objects are equal, FALSE otherwise
+	 */
+	bool (*equals_function) (linked_list_t *this, linked_list_t *other,
+							 bool (*)(void*,void*));
+
+	/**
 	 * Destroys a linked_list object.
 	 */
 	void (*destroy) (linked_list_t *this);
diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c
index 9988d80..956ce08 100644
--- a/src/libstrongswan/credentials/auth_cfg.c
+++ b/src/libstrongswan/credentials/auth_cfg.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2015 Tobias Brunner
+ * Copyright (C) 2008-2016 Tobias Brunner
  * Copyright (C) 2007-2009 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -46,11 +46,13 @@ ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_AC_CERT,
 	"RULE_SUBJECT_CERT",
 	"RULE_CRL_VALIDATION",
 	"RULE_OCSP_VALIDATION",
+	"RULE_CERT_VALIDATION_SUSPENDED",
 	"RULE_GROUP",
 	"RULE_RSA_STRENGTH",
 	"RULE_ECDSA_STRENGTH",
 	"RULE_BLISS_STRENGTH",
 	"RULE_SIGNATURE_SCHEME",
+	"RULE_IKE_SIGNATURE_SCHEME",
 	"RULE_CERT_POLICY",
 	"HELPER_IM_CERT",
 	"HELPER_SUBJECT_CERT",
@@ -79,6 +81,7 @@ static inline bool is_multi_value_rule(auth_rule_t type)
 		case AUTH_RULE_AAA_IDENTITY:
 		case AUTH_RULE_XAUTH_IDENTITY:
 		case AUTH_RULE_XAUTH_BACKEND:
+		case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
 		case AUTH_HELPER_SUBJECT_CERT:
 		case AUTH_HELPER_SUBJECT_HASH_URL:
 		case AUTH_RULE_MAX:
@@ -91,6 +94,7 @@ static inline bool is_multi_value_rule(auth_rule_t type)
 		case AUTH_RULE_IM_CERT:
 		case AUTH_RULE_CERT_POLICY:
 		case AUTH_RULE_SIGNATURE_SCHEME:
+		case AUTH_RULE_IKE_SIGNATURE_SCHEME:
 		case AUTH_HELPER_IM_CERT:
 		case AUTH_HELPER_IM_HASH_URL:
 		case AUTH_HELPER_REVOCATION_CERT:
@@ -211,6 +215,8 @@ static void init_entry(entry_t *this, auth_rule_t type, va_list args)
 		case AUTH_RULE_ECDSA_STRENGTH:
 		case AUTH_RULE_BLISS_STRENGTH:
 		case AUTH_RULE_SIGNATURE_SCHEME:
+		case AUTH_RULE_IKE_SIGNATURE_SCHEME:
+		case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
 			/* integer type */
 			this->value = (void*)(uintptr_t)va_arg(args, u_int);
 			break;
@@ -260,6 +266,8 @@ static bool entry_equals(entry_t *e1, entry_t *e2)
 		case AUTH_RULE_ECDSA_STRENGTH:
 		case AUTH_RULE_BLISS_STRENGTH:
 		case AUTH_RULE_SIGNATURE_SCHEME:
+		case AUTH_RULE_IKE_SIGNATURE_SCHEME:
+		case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
 		{
 			return e1->value == e2->value;
 		}
@@ -351,6 +359,8 @@ static void destroy_entry_value(entry_t *entry)
 		case AUTH_RULE_ECDSA_STRENGTH:
 		case AUTH_RULE_BLISS_STRENGTH:
 		case AUTH_RULE_SIGNATURE_SCHEME:
+		case AUTH_RULE_IKE_SIGNATURE_SCHEME:
+		case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
 		case AUTH_RULE_MAX:
 			break;
 	}
@@ -383,6 +393,8 @@ static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator,
 			case AUTH_RULE_ECDSA_STRENGTH:
 			case AUTH_RULE_BLISS_STRENGTH:
 			case AUTH_RULE_SIGNATURE_SCHEME:
+			case AUTH_RULE_IKE_SIGNATURE_SCHEME:
+			case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
 				/* integer type */
 				entry->value = (void*)(uintptr_t)va_arg(args, u_int);
 				break;
@@ -459,11 +471,13 @@ METHOD(auth_cfg_t, get, void*,
 		case AUTH_RULE_BLISS_STRENGTH:
 			return (void*)0;
 		case AUTH_RULE_SIGNATURE_SCHEME:
+		case AUTH_RULE_IKE_SIGNATURE_SCHEME:
 			return (void*)HASH_UNKNOWN;
 		case AUTH_RULE_CRL_VALIDATION:
 		case AUTH_RULE_OCSP_VALIDATION:
 			return (void*)VALIDATION_FAILED;
 		case AUTH_RULE_IDENTITY_LOOSE:
+		case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
 			return (void*)FALSE;
 		case AUTH_RULE_IDENTITY:
 		case AUTH_RULE_EAP_IDENTITY:
@@ -510,6 +524,183 @@ static void add(private_auth_cfg_t *this, auth_rule_t type, ...)
 	}
 }
 
+METHOD(auth_cfg_t, add_pubkey_constraints, void,
+	private_auth_cfg_t *this, char* constraints, bool ike)
+{
+	enumerator_t *enumerator;
+	bool is_ike = FALSE, ike_added = FALSE;
+	key_type_t expected_type = -1;
+	auth_rule_t expected_strength = AUTH_RULE_MAX;
+	int strength;
+	char *token;
+	auth_rule_t type;
+	void *value;
+
+	enumerator = enumerator_create_token(constraints, "-", "");
+	while (enumerator->enumerate(enumerator, &token))
+	{
+		bool found = FALSE;
+		int i;
+		struct {
+			char *name;
+			signature_scheme_t scheme;
+			key_type_t key;
+		} schemes[] = {
+			{ "md5",		SIGN_RSA_EMSA_PKCS1_MD5,		KEY_RSA,	},
+			{ "sha1",		SIGN_RSA_EMSA_PKCS1_SHA1,		KEY_RSA,	},
+			{ "sha224",		SIGN_RSA_EMSA_PKCS1_SHA224,		KEY_RSA,	},
+			{ "sha256",		SIGN_RSA_EMSA_PKCS1_SHA256,		KEY_RSA,	},
+			{ "sha384",		SIGN_RSA_EMSA_PKCS1_SHA384,		KEY_RSA,	},
+			{ "sha512",		SIGN_RSA_EMSA_PKCS1_SHA512,		KEY_RSA,	},
+			{ "sha1",		SIGN_ECDSA_WITH_SHA1_DER,		KEY_ECDSA,	},
+			{ "sha256",		SIGN_ECDSA_WITH_SHA256_DER,		KEY_ECDSA,	},
+			{ "sha384",		SIGN_ECDSA_WITH_SHA384_DER,		KEY_ECDSA,	},
+			{ "sha512",		SIGN_ECDSA_WITH_SHA512_DER,		KEY_ECDSA,	},
+			{ "sha256",		SIGN_ECDSA_256,					KEY_ECDSA,	},
+			{ "sha384",		SIGN_ECDSA_384,					KEY_ECDSA,	},
+			{ "sha512",		SIGN_ECDSA_521,					KEY_ECDSA,	},
+			{ "sha256",		SIGN_BLISS_WITH_SHA2_256,		KEY_BLISS,	},
+			{ "sha384",		SIGN_BLISS_WITH_SHA2_384,		KEY_BLISS,	},
+			{ "sha512",		SIGN_BLISS_WITH_SHA2_512,		KEY_BLISS,	},
+		};
+
+		if (expected_strength != AUTH_RULE_MAX)
+		{	/* expecting a key strength token */
+			strength = atoi(token);
+			if (strength)
+			{
+				add(this, expected_strength, (uintptr_t)strength);
+			}
+			expected_strength = AUTH_RULE_MAX;
+			if (strength)
+			{
+				continue;
+			}
+		}
+		if (streq(token, "rsa") || streq(token, "ike:rsa"))
+		{
+			expected_type = KEY_RSA;
+			expected_strength = AUTH_RULE_RSA_STRENGTH;
+			is_ike = strpfx(token, "ike:");
+			continue;
+		}
+		if (streq(token, "ecdsa") || streq(token, "ike:ecdsa"))
+		{
+			expected_type = KEY_ECDSA;
+			expected_strength = AUTH_RULE_ECDSA_STRENGTH;
+			is_ike = strpfx(token, "ike:");
+			continue;
+		}
+		if (streq(token, "bliss") || streq(token, "ike:bliss"))
+		{
+			expected_type = KEY_BLISS;
+			expected_strength = AUTH_RULE_BLISS_STRENGTH;
+			is_ike = strpfx(token, "ike:");
+			continue;
+		}
+		if (streq(token, "pubkey") || streq(token, "ike:pubkey"))
+		{
+			expected_type = KEY_ANY;
+			is_ike = strpfx(token, "ike:");
+			continue;
+		}
+		if (is_ike && !ike)
+		{
+			continue;
+		}
+
+		for (i = 0; i < countof(schemes); i++)
+		{
+			if (streq(schemes[i].name, token))
+			{
+				if (expected_type == KEY_ANY || expected_type == schemes[i].key)
+				{
+					if (is_ike)
+					{
+						add(this, AUTH_RULE_IKE_SIGNATURE_SCHEME,
+							(uintptr_t)schemes[i].scheme);
+						ike_added = TRUE;
+					}
+					else
+					{
+						add(this, AUTH_RULE_SIGNATURE_SCHEME,
+						   (uintptr_t)schemes[i].scheme);
+					}
+				}
+				found = TRUE;
+			}
+		}
+		if (!found)
+		{
+			DBG1(DBG_CFG, "ignoring invalid auth token: '%s'", token);
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	/* if no explicit IKE signature contraints were added we add them for all
+	 * configured signature contraints */
+	if (ike && !ike_added &&
+		lib->settings->get_bool(lib->settings,
+							"%s.signature_authentication_constraints", TRUE,
+							lib->ns))
+	{
+		enumerator = create_enumerator(this);
+		while (enumerator->enumerate(enumerator, &type, &value))
+		{
+			if (type == AUTH_RULE_SIGNATURE_SCHEME)
+			{
+				add(this, AUTH_RULE_IKE_SIGNATURE_SCHEME,
+					(uintptr_t)value);
+			}
+		}
+		enumerator->destroy(enumerator);
+	}
+}
+
+/**
+ * Check if signature schemes of a specific type are compliant
+ */
+static bool complies_scheme(private_auth_cfg_t *this, auth_cfg_t *constraints,
+							auth_rule_t type, bool log_error)
+{
+	enumerator_t *e1, *e2;
+	auth_rule_t t1, t2;
+	signature_scheme_t scheme;
+	void *value;
+	bool success = TRUE;
+
+	e2 = create_enumerator(this);
+	while (e2->enumerate(e2, &t2, &scheme))
+	{
+		if (t2 == type)
+		{
+			success = FALSE;
+			e1 = constraints->create_enumerator(constraints);
+			while (e1->enumerate(e1, &t1, &value))
+			{
+				if (t1 == type && (uintptr_t)value == scheme)
+				{
+					success = TRUE;
+					break;
+				}
+			}
+			e1->destroy(e1);
+			if (!success)
+			{
+				if (log_error)
+				{
+					DBG1(DBG_CFG, "%s signature scheme %N not acceptable",
+						 AUTH_RULE_SIGNATURE_SCHEME == type ? "X.509" : "IKE",
+						 signature_scheme_names, (int)scheme);
+				}
+				break;
+			}
+		}
+	}
+	e2->destroy(e2);
+	return success;
+}
+
 METHOD(auth_cfg_t, complies, bool,
 	private_auth_cfg_t *this, auth_cfg_t *constraints, bool log_error)
 {
@@ -518,7 +709,7 @@ METHOD(auth_cfg_t, complies, bool,
 	bool ca_match = FALSE, cert_match = FALSE;
 	identification_t *require_group = NULL;
 	certificate_t *require_ca = NULL, *require_cert = NULL;
-	signature_scheme_t scheme = SIGN_UNKNOWN;
+	signature_scheme_t ike_scheme = SIGN_UNKNOWN, scheme = SIGN_UNKNOWN;
 	u_int strength = 0;
 	auth_rule_t t1, t2;
 	char *key_type;
@@ -573,6 +764,11 @@ METHOD(auth_cfg_t, complies, bool,
 			{
 				uintptr_t validated;
 
+				if (get(this, AUTH_RULE_CERT_VALIDATION_SUSPENDED))
+				{	/* skip validation, may happen later */
+					break;
+				}
+
 				e2 = create_enumerator(this);
 				while (e2->enumerate(e2, &t2, &validated))
 				{
@@ -714,6 +910,11 @@ METHOD(auth_cfg_t, complies, bool,
 				strength = (uintptr_t)value;
 				break;
 			}
+			case AUTH_RULE_IKE_SIGNATURE_SCHEME:
+			{
+				ike_scheme = (uintptr_t)value;
+				break;
+			}
 			case AUTH_RULE_SIGNATURE_SCHEME:
 			{
 				scheme = (uintptr_t)value;
@@ -745,6 +946,8 @@ METHOD(auth_cfg_t, complies, bool,
 				/* just an indication when verifying AUTH_RULE_IDENTITY */
 			case AUTH_RULE_XAUTH_BACKEND:
 				/* not enforced, just a hint for local authentication */
+			case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
+				/* not a constraint */
 			case AUTH_HELPER_IM_CERT:
 			case AUTH_HELPER_SUBJECT_CERT:
 			case AUTH_HELPER_IM_HASH_URL:
@@ -766,35 +969,13 @@ METHOD(auth_cfg_t, complies, bool,
 	 * signature schemes. */
 	if (success && scheme != SIGN_UNKNOWN)
 	{
-		e2 = create_enumerator(this);
-		while (e2->enumerate(e2, &t2, &scheme))
-		{
-			if (t2 == AUTH_RULE_SIGNATURE_SCHEME)
-			{
-				success = FALSE;
-				e1 = constraints->create_enumerator(constraints);
-				while (e1->enumerate(e1, &t1, &value))
-				{
-					if (t1 == AUTH_RULE_SIGNATURE_SCHEME &&
-						(uintptr_t)value == scheme)
-					{
-						success = TRUE;
-						break;
-					}
-				}
-				e1->destroy(e1);
-				if (!success)
-				{
-					if (log_error)
-					{
-						DBG1(DBG_CFG, "signature scheme %N not acceptable",
-							 signature_scheme_names, (int)scheme);
-					}
-					break;
-				}
-			}
-		}
-		e2->destroy(e2);
+		success = complies_scheme(this, constraints,
+								  AUTH_RULE_SIGNATURE_SCHEME, log_error);
+	}
+	if (success && ike_scheme != SIGN_UNKNOWN)
+	{
+		success = complies_scheme(this, constraints,
+								  AUTH_RULE_IKE_SIGNATURE_SCHEME, log_error);
 	}
 
 	/* Check if we have a matching constraint (or none at all) for used
@@ -918,6 +1099,8 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy
 				case AUTH_RULE_ECDSA_STRENGTH:
 				case AUTH_RULE_BLISS_STRENGTH:
 				case AUTH_RULE_SIGNATURE_SCHEME:
+				case AUTH_RULE_IKE_SIGNATURE_SCHEME:
+				case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
 				{
 					add(this, type, (uintptr_t)value);
 					break;
@@ -1088,6 +1271,8 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
 			case AUTH_RULE_ECDSA_STRENGTH:
 			case AUTH_RULE_BLISS_STRENGTH:
 			case AUTH_RULE_SIGNATURE_SCHEME:
+			case AUTH_RULE_IKE_SIGNATURE_SCHEME:
+			case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
 				clone->add(clone, type, (uintptr_t)value);
 				break;
 			case AUTH_RULE_MAX:
@@ -1116,6 +1301,7 @@ auth_cfg_t *auth_cfg_create()
 	INIT(this,
 		.public = {
 			.add = (void(*)(auth_cfg_t*, auth_rule_t type, ...))add,
+			.add_pubkey_constraints = _add_pubkey_constraints,
 			.get = _get,
 			.create_enumerator = _create_enumerator,
 			.replace = (void(*)(auth_cfg_t*,enumerator_t*,auth_rule_t,...))replace,
diff --git a/src/libstrongswan/credentials/auth_cfg.h b/src/libstrongswan/credentials/auth_cfg.h
index 53f1b38..6940069 100644
--- a/src/libstrongswan/credentials/auth_cfg.h
+++ b/src/libstrongswan/credentials/auth_cfg.h
@@ -94,6 +94,8 @@ enum auth_rule_t {
 	AUTH_RULE_CRL_VALIDATION,
 	/** result of a OCSP validation, cert_validation_t */
 	AUTH_RULE_OCSP_VALIDATION,
+	/** CRL/OCSP validation is disabled, bool */
+	AUTH_RULE_CERT_VALIDATION_SUSPENDED,
 	/** subject is member of a group, identification_t*
 	 * The group membership constraint is fulfilled if the subject is member of
 	 * one group defined in the constraints. */
@@ -106,6 +108,8 @@ enum auth_rule_t {
 	AUTH_RULE_BLISS_STRENGTH,
 	/** required signature scheme, signature_scheme_t */
 	AUTH_RULE_SIGNATURE_SCHEME,
+	/** required signature scheme for IKE authentication, signature_scheme_t */
+	AUTH_RULE_IKE_SIGNATURE_SCHEME,
 	/** certificatePolicy constraint, numerical OID as char* */
 	AUTH_RULE_CERT_POLICY,
 
@@ -182,6 +186,15 @@ struct auth_cfg_t {
 	void (*add)(auth_cfg_t *this, auth_rule_t rule, ...);
 
 	/**
+	 * Add public key and signature scheme constraints to the set.
+	 *
+	 * @param constraints	constraints string (e.g. "rsa-sha384")
+	 * @param ike			whether to add/parse constraints for IKE signatures
+	 */
+	void (*add_pubkey_constraints)(auth_cfg_t *this, char *constraints,
+								   bool ike);
+
+	/**
 	 * Get a rule value.
 	 *
 	 * For rules we expect only once the latest value is returned.
diff --git a/src/libstrongswan/credentials/certificates/certificate.c b/src/libstrongswan/credentials/certificates/certificate.c
index b281c16..7610829 100644
--- a/src/libstrongswan/credentials/certificates/certificate.c
+++ b/src/libstrongswan/credentials/certificates/certificate.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2007 Martin Willi
- * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR 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
@@ -22,10 +23,10 @@ ENUM(certificate_type_names, CERT_ANY, CERT_GPG,
 	"ANY",
 	"X509",
 	"X509_CRL",
-	"X509_OCSP_REQUEST",
-	"X509_OCSP_RESPONSE",
+	"OCSP_REQUEST",
+	"OCSP_RESPONSE",
 	"X509_AC",
-	"TRUSTED_PUBKEY",
+	"PUBKEY",
 	"PKCS10_REQUEST",
 	"PGP",
 );
diff --git a/src/libstrongswan/credentials/certificates/certificate_printer.c b/src/libstrongswan/credentials/certificates/certificate_printer.c
new file mode 100644
index 0000000..c618e80
--- /dev/null
+++ b/src/libstrongswan/credentials/certificates/certificate_printer.c
@@ -0,0 +1,753 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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.
+ */
+
+#include "certificate_printer.h"
+#include "credentials/certificates/x509.h"
+#include "credentials/certificates/crl.h"
+#include "credentials/certificates/ac.h"
+#include "credentials/certificates/ocsp_response.h"
+#include "credentials/certificates/pgp_certificate.h"
+
+#include <asn1/asn1.h>
+#include <asn1/oid.h>
+#include <selectors/traffic_selector.h>
+
+#include <time.h>
+
+typedef struct private_certificate_printer_t private_certificate_printer_t;
+
+/**
+ * Private data of an certificate_printer_t object.
+ */
+struct private_certificate_printer_t {
+
+	/**
+	 * Public certificate_printer_t interface.
+	 */
+	certificate_printer_t public;
+
+	/**
+	 * File to print to
+	 */
+	FILE *f;
+
+	/**
+	 * Print detailed certificate information
+	 */
+	bool detailed;
+
+	/**
+	 * Print time information in UTC
+	 */
+	bool utc;
+
+	/**
+	 * Previous certificate type
+	 */
+	certificate_type_t type;
+
+	/**
+	 * Previous X.509 certificate flag
+	 */
+	x509_flag_t flag;
+
+};
+
+/**
+ * Print X509 specific certificate information
+ */
+static void print_x509(private_certificate_printer_t *this, x509_t *x509)
+{
+	enumerator_t *enumerator;
+	identification_t *id;
+	traffic_selector_t *block;
+	chunk_t chunk;
+	bool first;
+	char *uri;
+	int len, explicit, inhibit;
+	x509_flag_t flags;
+	x509_cdp_t *cdp;
+	x509_cert_policy_t *policy;
+	x509_policy_mapping_t *mapping;
+	FILE *f = this->f;
+
+	chunk = chunk_skip_zero(x509->get_serial(x509));
+	fprintf(f, "  serial:    %#B\n", &chunk);
+
+	first = TRUE;
+	enumerator = x509->create_subjectAltName_enumerator(x509);
+	while (enumerator->enumerate(enumerator, &id))
+	{
+		if (first)
+		{
+			fprintf(f, "  altNames:  ");
+			first = FALSE;
+		}
+		else
+		{
+			fprintf(f, ", ");
+		}
+		fprintf(f, "%Y", id);
+	}
+	if (!first)
+	{
+		fprintf(f, "\n");
+	}
+	enumerator->destroy(enumerator);
+
+	if (this->detailed)
+	{
+		flags = x509->get_flags(x509);
+		if (flags != X509_NONE)
+		{
+			fprintf(f, "  flags:     ");
+			if (flags & X509_CA)
+			{
+				fprintf(f, "CA ");
+			}
+			if (flags & X509_CRL_SIGN)
+			{
+				fprintf(f, "CRLSign ");
+			}
+			if (flags & X509_OCSP_SIGNER)
+			{
+				fprintf(f, "ocspSigning ");
+			}
+			if (flags & X509_SERVER_AUTH)
+			{
+				fprintf(f, "serverAuth ");
+			}
+			if (flags & X509_CLIENT_AUTH)
+			{
+				fprintf(f, "clientAuth ");
+			}
+			if (flags & X509_IKE_INTERMEDIATE)
+			{
+				fprintf(f, "ikeIntermediate ");
+			}
+			if (flags & X509_MS_SMARTCARD_LOGON)
+			{
+				fprintf(f, "msSmartcardLogon");
+			}
+			if (flags & X509_SELF_SIGNED)
+			{
+				fprintf(f, "self-signed ");
+			}
+			fprintf(f, "\n");
+		}
+
+		first = TRUE;
+		enumerator = x509->create_crl_uri_enumerator(x509);
+		while (enumerator->enumerate(enumerator, &cdp))
+		{
+			if (first)
+			{
+				fprintf(f, "  CRL URIs:  %s", cdp->uri);
+				first = FALSE;
+			}
+			else
+			{
+				fprintf(f, "           %s", cdp->uri);
+			}
+			if (cdp->issuer)
+			{
+				fprintf(f, " (CRL issuer: %Y)", cdp->issuer);
+			}
+			fprintf(f, "\n");
+		}
+		enumerator->destroy(enumerator);
+
+		first = TRUE;
+		enumerator = x509->create_ocsp_uri_enumerator(x509);
+		while (enumerator->enumerate(enumerator, &uri))
+		{
+			if (first)
+			{
+				fprintf(f, "  OCSP URIs: %s\n", uri);
+				first = FALSE;
+			}
+			else
+			{
+				fprintf(f, "           %s\n", uri);
+			}
+		}
+		enumerator->destroy(enumerator);
+
+		len = x509->get_constraint(x509, X509_PATH_LEN);
+		if (len != X509_NO_CONSTRAINT)
+		{
+			fprintf(f, "  pathlen:   %d\n", len);
+		}
+
+		first = TRUE;
+		enumerator = x509->create_name_constraint_enumerator(x509, TRUE);
+		while (enumerator->enumerate(enumerator, &id))
+		{
+			if (first)
+			{
+				fprintf(f, "  permitted nameConstraints:\n");
+				first = FALSE;
+			}
+			fprintf(f, "           %Y\n", id);
+		}
+		enumerator->destroy(enumerator);
+
+		first = TRUE;
+		enumerator = x509->create_name_constraint_enumerator(x509, FALSE);
+		while (enumerator->enumerate(enumerator, &id))
+		{
+			if (first)
+			{
+				fprintf(f, "  excluded nameConstraints:\n");
+				first = FALSE;
+			}
+			fprintf(f, "           %Y\n", id);
+		}
+		enumerator->destroy(enumerator);
+
+		first = TRUE;
+		enumerator = x509->create_cert_policy_enumerator(x509);
+		while (enumerator->enumerate(enumerator, &policy))
+		{
+			char *oid;
+
+			if (first)
+			{
+				fprintf(f, "  certificatePolicies:\n");
+				first = FALSE;
+			}
+			oid = asn1_oid_to_string(policy->oid);
+			if (oid)
+			{
+				fprintf(f, "             %s\n", oid);
+				free(oid);
+			}
+			else
+			{
+				fprintf(f, "             %#B\n", &policy->oid);
+			}
+			if (policy->cps_uri)
+			{
+				fprintf(f, "             CPS: %s\n", policy->cps_uri);
+			}
+			if (policy->unotice_text)
+			{
+				fprintf(f, "             Notice: %s\n", policy->unotice_text);
+			}
+		}
+		enumerator->destroy(enumerator);
+
+		first = TRUE;
+		enumerator = x509->create_policy_mapping_enumerator(x509);
+		while (enumerator->enumerate(enumerator, &mapping))
+		{
+			char *issuer_oid, *subject_oid;
+
+			if (first)
+			{
+				fprintf(f, "  policyMappings:\n");
+				first = FALSE;
+			}
+			issuer_oid = asn1_oid_to_string(mapping->issuer);
+			subject_oid = asn1_oid_to_string(mapping->subject);
+			fprintf(f, "           %s => %s\n", issuer_oid, subject_oid);
+			free(issuer_oid);
+			free(subject_oid);
+		}
+		enumerator->destroy(enumerator);
+
+		explicit = x509->get_constraint(x509, X509_REQUIRE_EXPLICIT_POLICY);
+		inhibit = x509->get_constraint(x509, X509_INHIBIT_POLICY_MAPPING);
+		len = x509->get_constraint(x509, X509_INHIBIT_ANY_POLICY);
+
+		if (explicit != X509_NO_CONSTRAINT || inhibit != X509_NO_CONSTRAINT ||
+			len != X509_NO_CONSTRAINT)
+		{
+			fprintf(f, "  policyConstraints:\n");
+			if (explicit != X509_NO_CONSTRAINT)
+			{
+				fprintf(f, "           requireExplicitPolicy: %d\n", explicit);
+			}
+			if (inhibit != X509_NO_CONSTRAINT)
+			{
+				fprintf(f, "           inhibitPolicyMapping: %d\n", inhibit);
+			}
+			if (len != X509_NO_CONSTRAINT)
+			{
+				fprintf(f, "           inhibitAnyPolicy: %d\n", len);
+			}
+		}
+
+		if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
+		{
+			first = TRUE;
+			fprintf(f, "  addresses: ");
+			enumerator = x509->create_ipAddrBlock_enumerator(x509);
+			while (enumerator->enumerate(enumerator, &block))
+			{
+				if (first)
+				{
+					first = FALSE;
+				}
+				else
+				{
+					fprintf(f, ", ");
+				}
+				fprintf(f, "%R", block);
+			}
+			enumerator->destroy(enumerator);
+			fprintf(f, "\n");
+		}
+	}
+
+	chunk = x509->get_authKeyIdentifier(x509);
+	if (chunk.ptr)
+	{
+		fprintf(f, "  authkeyId: %#B\n", &chunk);
+	}
+
+	chunk = x509->get_subjectKeyIdentifier(x509);
+	if (chunk.ptr)
+	{
+		fprintf(f, "  subjkeyId: %#B\n", &chunk);
+	}
+}
+
+/**
+ * Print CRL specific information
+ */
+static void print_crl(private_certificate_printer_t *this, crl_t *crl)
+{
+	enumerator_t *enumerator;
+	time_t ts;
+	crl_reason_t reason;
+	chunk_t chunk;
+	int count = 0;
+	bool first;
+	x509_cdp_t *cdp;
+	FILE *f = this->f;
+
+	chunk = chunk_skip_zero(crl->get_serial(crl));
+	fprintf(f, "  serial:    %#B\n", &chunk);
+
+	if (crl->is_delta_crl(crl, &chunk))
+	{
+		chunk = chunk_skip_zero(chunk);
+		fprintf(f, "  delta CRL: for serial %#B\n", &chunk);
+	}
+	chunk = crl->get_authKeyIdentifier(crl);
+	fprintf(f, "  authKeyId: %#B\n", &chunk);
+
+	first = TRUE;
+	enumerator = crl->create_delta_crl_uri_enumerator(crl);
+	while (enumerator->enumerate(enumerator, &cdp))
+	{
+		if (first)
+		{
+			fprintf(f, "  freshest:  %s", cdp->uri);
+			first = FALSE;
+		}
+		else
+		{
+			fprintf(f, "             %s", cdp->uri);
+		}
+		if (cdp->issuer)
+		{
+			fprintf(f, " (CRL issuer: %Y)", cdp->issuer);
+		}
+		fprintf(f, "\n");
+	}
+	enumerator->destroy(enumerator);
+
+	enumerator = crl->create_enumerator(crl);
+	while (enumerator->enumerate(enumerator, &chunk, &ts, &reason))
+	{
+		count++;
+	}
+	enumerator->destroy(enumerator);
+
+	fprintf(f, "  %d revoked certificate%s%s\n", count, (count == 1) ? "" : "s",
+				(count && this->detailed) ? ":" : "");
+
+	if (this->detailed)
+	{
+		enumerator = crl->create_enumerator(crl);
+		while (enumerator->enumerate(enumerator, &chunk, &ts, &reason))
+		{
+			chunk = chunk_skip_zero(chunk);
+			fprintf(f, "    %#B: %T, %N\n", &chunk, &ts, this->utc,
+											crl_reason_names, reason);
+		}
+		enumerator->destroy(enumerator);
+	}
+}
+
+/**
+ * Print AC specific information
+ */
+static void print_ac(private_certificate_printer_t *this, ac_t *ac)
+{
+	ac_group_type_t type;
+	identification_t *id;
+	enumerator_t *groups;
+	chunk_t chunk;
+	bool first = TRUE;
+	FILE *f = this->f;
+
+	chunk = chunk_skip_zero(ac->get_serial(ac));
+	fprintf(f, "  serial:    %#B\n", &chunk);
+
+	id = ac->get_holderIssuer(ac);
+	if (id)
+	{
+		fprintf(f, "  hissuer:  \"%Y\"\n", id);
+	}
+	chunk = chunk_skip_zero(ac->get_holderSerial(ac));
+	if (chunk.ptr)
+	{
+		fprintf(f, "  hserial:   %#B\n", &chunk);
+	}
+	groups = ac->create_group_enumerator(ac);
+	while (groups->enumerate(groups, &type, &chunk))
+	{
+		int oid;
+		char *str;
+
+		if (first)
+		{
+			fprintf(f, "  groups:    ");
+			first = FALSE;
+		}
+		else
+		{
+			fprintf(f, "             ");
+		}
+		switch (type)
+		{
+			case AC_GROUP_TYPE_STRING:
+				fprintf(f, "%.*s", (int)chunk.len, chunk.ptr);
+				break;
+			case AC_GROUP_TYPE_OID:
+				oid = asn1_known_oid(chunk);
+				if (oid == OID_UNKNOWN)
+				{
+					str = asn1_oid_to_string(chunk);
+					if (str)
+					{
+						fprintf(f, "%s", str);
+						free(str);
+					}
+					else
+					{
+						fprintf(f, "OID:%#B", &chunk);
+					}
+				}
+				else
+				{
+					fprintf(f, "%s", oid_names[oid].name);
+				}
+				break;
+			case AC_GROUP_TYPE_OCTETS:
+				fprintf(f, "%#B", &chunk);
+				break;
+		}
+		fprintf(f, "\n");
+	}
+	groups->destroy(groups);
+
+	chunk = ac->get_authKeyIdentifier(ac);
+	if (chunk.ptr)
+	{
+		fprintf(f, "  authkey:  %#B\n", &chunk);
+	}
+}
+
+/**
+ * Print OCSP response specific information
+ */
+static void print_ocsp_response(private_certificate_printer_t *this,
+								ocsp_response_t *ocsp_response)
+{
+	enumerator_t *enumerator;
+	chunk_t serialNumber;
+	cert_validation_t status;
+	char *status_text;
+	time_t revocationTime;
+	crl_reason_t *revocationReason;
+	bool first = TRUE;
+	FILE *f = this->f;
+
+	if (this->detailed)
+	{
+		fprintf(f, "  responses: ");
+
+		enumerator = ocsp_response->create_response_enumerator(ocsp_response);
+		while (enumerator->enumerate(enumerator, &serialNumber, &status,
+									 &revocationTime, &revocationReason))
+		{
+			if (first)
+			{
+				first = FALSE;
+			}
+			else
+			{
+				fprintf(f, "             ");
+			}
+			serialNumber = chunk_skip_zero(serialNumber);
+
+			switch (status)
+			{
+				case VALIDATION_GOOD:
+					status_text = "good";
+					break;
+				case VALIDATION_REVOKED:
+					status_text = "revoked";
+					break;
+				default:
+					status_text = "unknown";
+			}
+			fprintf(f, "%#B: %s", &serialNumber, status_text);
+
+			if (status == VALIDATION_REVOKED)
+			{
+				fprintf(f, " on %T, %N", &revocationTime, this->utc,
+							 crl_reason_names, revocationReason);
+			}
+			fprintf(f, "\n");
+		}
+		enumerator->destroy(enumerator);
+	}
+}
+
+/**
+ * Print public key information
+ */
+static void print_pubkey(private_certificate_printer_t *this, public_key_t *key,
+						 bool has_privkey)
+{
+	chunk_t chunk;
+	FILE *f = this->f;
+
+	fprintf(f, "  pubkey:    %N %d bits", key_type_names, key->get_type(key),
+				key->get_keysize(key));
+	if (has_privkey)
+	{
+		fprintf(f, ", has private key");
+	}
+	fprintf(f, "\n");
+	if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &chunk))
+	{
+		fprintf(f, "  keyid:     %#B\n", &chunk);
+	}
+	if (key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &chunk))
+	{
+		fprintf(f, "  subjkey:   %#B\n", &chunk);
+	}
+}
+
+METHOD(certificate_printer_t, print, void,
+	private_certificate_printer_t *this, certificate_t *cert, bool has_privkey)
+{
+	time_t now, notAfter, notBefore;
+	certificate_type_t type;
+	identification_t *subject;
+	char *t0, *t1, *t2;
+	public_key_t *key;
+	FILE *f = this->f;
+
+	now = time(NULL);
+	type = cert->get_type(cert);
+	subject = cert->get_subject(cert);
+
+	if ((type != CERT_X509_CRL && type != CERT_X509_OCSP_RESPONSE &&
+		 type != CERT_TRUSTED_PUBKEY) ||
+	    (type == CERT_TRUSTED_PUBKEY && subject->get_type(subject) != ID_KEY_ID))
+	{
+		fprintf(f, "  subject:  \"%Y\"\n", subject);
+	}
+	if (type != CERT_TRUSTED_PUBKEY && type != CERT_GPG)
+	{
+		fprintf(f, "  issuer:   \"%Y\"\n", cert->get_issuer(cert));
+	}
+
+	/* list validity if set */
+	cert->get_validity(cert, &now, &notBefore, &notAfter);
+	if (notBefore != UNDEFINED_TIME && notAfter != UNDEFINED_TIME)
+	{
+		if (type == CERT_GPG)
+		{
+			fprintf(f, "  created:   %T\n", &notBefore, this->utc);
+			fprintf(f, "  until:     %T%s\n", &notAfter, this->utc,
+				(notAfter == TIME_32_BIT_SIGNED_MAX) ?" expires never" : "");
+		}
+		else
+		{
+			 if (type == CERT_X509_CRL || type == CERT_X509_OCSP_RESPONSE)
+			{
+				t0 = "update:  ";
+				t1 = "this on";
+				t2 = "next on";
+			}
+			else
+			{
+				t0 = "validity:";
+				t1 = "not before";
+				t2 = "not after ";
+			}
+			fprintf(f, "  %s  %s %T, ", t0, t1, &notBefore, this->utc);
+			if (now < notBefore)
+			{
+				fprintf(f, "not valid yet (valid in %V)\n", &now, &notBefore);
+			}
+			else
+			{
+				fprintf(f, "ok\n");
+			}
+			fprintf(f, "             %s %T, ", t2, &notAfter, this->utc);
+			if (now > notAfter)
+			{
+				fprintf(f, "expired (%V ago)\n", &now, &notAfter);
+			}
+			else
+			{
+				fprintf(f, "ok (expires in %V)\n", &now, &notAfter);
+			}
+		}
+	}
+
+	switch (cert->get_type(cert))
+	{
+		case CERT_X509:
+			print_x509(this, (x509_t*)cert);
+			break;
+		case CERT_X509_CRL:
+			print_crl(this, (crl_t*)cert);
+			break;
+		case CERT_X509_AC:
+			print_ac(this, (ac_t*)cert);
+			break;
+		case CERT_X509_OCSP_RESPONSE:
+			print_ocsp_response(this, (ocsp_response_t*)cert);
+			break;
+		case CERT_TRUSTED_PUBKEY:
+		default:
+			break;
+	}
+	if (type == CERT_GPG)
+	{
+		pgp_certificate_t *pgp_cert = (pgp_certificate_t*)cert;
+		chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert);
+
+		fprintf(f, "  pgpDigest: %#B\n", &fingerprint);
+	}
+	key = cert->get_public_key(cert);
+	if (key)
+	{
+		print_pubkey(this, key, has_privkey);
+		key->destroy(key);
+	}
+}
+
+METHOD(certificate_printer_t, print_caption, void,
+	private_certificate_printer_t *this, certificate_type_t type,
+	x509_flag_t flag)
+{
+	char *caption;
+
+	if (type != this->type || (type == CERT_X509 && flag != this->flag))
+	{
+		switch (type)
+		{
+			case CERT_X509:
+				switch (flag)
+				{
+					case X509_NONE:
+						caption = "X.509 End Entity Certificate";
+						break;
+					case X509_CA:
+						caption = "X.509 CA Certificate";
+						break;
+					case X509_AA:
+						caption = "X.509 AA Certificate";
+						break;
+					case X509_OCSP_SIGNER:
+						caption = "X.509 OCSP Signer Certificate";
+						break;
+					default:
+						return;
+				}
+				break;
+			case CERT_X509_AC:
+				caption = "X.509 Attribute Certificate";
+				break;
+			case CERT_X509_CRL:
+				caption = "X.509 CRL";
+				break;
+			case CERT_X509_OCSP_RESPONSE:
+				caption = "OCSP Response";
+				break;
+			case CERT_TRUSTED_PUBKEY:
+				caption = "Raw Public Key";
+				break;
+			case CERT_GPG:
+				caption = "PGP End Entity Certificate";
+				break;
+			default:
+				return;
+		}
+		fprintf(this->f, "\nList of %ss\n", caption);
+
+		/* Update to current type and flag value */
+		this->type = type;
+		if (type == CERT_X509)
+		{
+			this->flag = flag;
+		}
+	}
+	fprintf(this->f, "\n");
+}
+
+METHOD(certificate_printer_t, destroy, void,
+	private_certificate_printer_t *this)
+{
+	free(this);
+}
+
+/**
+ * See header
+ */
+certificate_printer_t *certificate_printer_create(FILE *f, bool detailed,
+												  bool utc)
+{
+	private_certificate_printer_t *this;
+
+	INIT(this,
+		.public = {
+			.print = _print,
+			.print_caption = _print_caption,
+			.destroy = _destroy,
+		},
+		.f = f,
+		.detailed = detailed,
+		.utc = utc,
+		.type = CERT_ANY,
+		.flag = X509_ANY,
+	);
+
+	return &this->public;
+}
diff --git a/src/libstrongswan/credentials/certificates/certificate_printer.h b/src/libstrongswan/credentials/certificates/certificate_printer.h
new file mode 100644
index 0000000..7953eb0
--- /dev/null
+++ b/src/libstrongswan/credentials/certificates/certificate_printer.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR 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 certificate_printer certificate_printer
+ * @{ @ingroup certificates
+ */
+
+#ifndef CERTIFICATE_PRINTER_H_
+#define CERTIFICATE_PRINTER_H_
+
+typedef struct certificate_printer_t certificate_printer_t;
+
+#include "credentials/certificates/certificate.h"
+#include "credentials/certificates/x509.h"
+
+#include <stdio.h>
+
+/**
+ * An object for printing certificate information.
+ */
+struct certificate_printer_t {
+
+	/**
+	 * Print a certificate.
+	 *
+	 * @param cert			certificate to be printed
+	 * @param has_privkey	indicates that certificate has a matching private key
+	 */
+	void (*print)(certificate_printer_t *this, certificate_t *cert,
+				  bool has_privkey);
+
+	/**
+	 * Print a caption if the certificate type changed.
+	 *
+	 * @param type		certificate type
+	 * @param flag		X.509 certificate flag
+	 */
+	void (*print_caption)(certificate_printer_t *this, certificate_type_t type,
+						  x509_flag_t flag);
+
+	/**
+	 * Destroy the certificate_printer object.
+	 */
+	void (*destroy)(certificate_printer_t *this);
+};
+
+/**
+ * Create a certificate_printer object
+ *
+ * @param f				file where print output is directed to (usually stdout)
+ * @param detailed		print more detailed certificate information
+ * @param utc			print time inforamtion in UTC
+ */
+certificate_printer_t* certificate_printer_create(FILE *f, bool detailed,
+												  bool utc);
+
+#endif /** CERTIFICATE_PRINTER_H_ @}*/
diff --git a/src/libstrongswan/credentials/certificates/ocsp_response.h b/src/libstrongswan/credentials/certificates/ocsp_response.h
index 9c5637b..c6a4c12 100644
--- a/src/libstrongswan/credentials/certificates/ocsp_response.h
+++ b/src/libstrongswan/credentials/certificates/ocsp_response.h
@@ -77,6 +77,13 @@ struct ocsp_response_t {
 	 * @return					enumerator over certificate_t*
 	 */
 	enumerator_t* (*create_cert_enumerator)(ocsp_response_t *this);
+
+	/**
+	 * Create an enumerator over the contained responses.
+	 *
+	 * @return					enumerator over major response fields
+	 */
+	enumerator_t* (*create_response_enumerator)(ocsp_response_t *this);
 };
 
 #endif /** OCSP_RESPONSE_H_ @}*/
diff --git a/src/libstrongswan/credentials/certificates/x509.c b/src/libstrongswan/credentials/certificates/x509.c
new file mode 100644
index 0000000..5eefa0b
--- /dev/null
+++ b/src/libstrongswan/credentials/certificates/x509.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR 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.
+ */
+
+#include "x509.h"
+
+ENUM_BEGIN(x509_flag_names, X509_NONE, X509_AA,
+	"NONE",
+	"CA",
+	"AA");
+ENUM_NEXT(x509_flag_names, X509_OCSP_SIGNER, X509_OCSP_SIGNER, X509_AA,
+	"OCSP");
+ENUM_NEXT(x509_flag_names, X509_ANY, X509_ANY, X509_OCSP_SIGNER,
+	"ANY");
+ENUM_END(x509_flag_names, X509_ANY);
+
diff --git a/src/libstrongswan/credentials/certificates/x509.h b/src/libstrongswan/credentials/certificates/x509.h
index 6cbfcde..601c034 100644
--- a/src/libstrongswan/credentials/certificates/x509.h
+++ b/src/libstrongswan/credentials/certificates/x509.h
@@ -46,6 +46,8 @@ enum x509_flag_t {
 	X509_AA =                 (1<<1),
 	/** cert has OCSP signer constraint */
 	X509_OCSP_SIGNER =        (1<<2),
+    /** cert has either CA, AA or OCSP constraint */
+	X509_ANY = X509_CA | X509_AA | X509_OCSP_SIGNER,
 	/** cert has serverAuth key usage */
 	X509_SERVER_AUTH =        (1<<3),
 	/** cert has clientAuth key usage */
@@ -62,6 +64,8 @@ enum x509_flag_t {
 	X509_MS_SMARTCARD_LOGON = (1<<9),
 };
 
+extern enum_name_t *x509_flag_names;
+
 /**
  * Different numerical X.509 constraints.
  */
diff --git a/src/libstrongswan/credentials/credential_manager.c b/src/libstrongswan/credentials/credential_manager.c
index 371e640..95c5cd7 100644
--- a/src/libstrongswan/credentials/credential_manager.c
+++ b/src/libstrongswan/credentials/credential_manager.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2015 Tobias Brunner
  * Copyright (C) 2007 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -917,6 +918,8 @@ METHOD(enumerator_t, trusted_destroy, void,
 	DESTROY_IF(this->auth);
 	DESTROY_IF(this->candidates);
 	this->failed->destroy_offset(this->failed, offsetof(certificate_t, destroy));
+	/* check for delayed certificate cache queue */
+	cache_queue(this->this);
 	free(this);
 }
 
@@ -985,7 +988,6 @@ METHOD(enumerator_t, public_destroy, void,
 		this->wrapper->destroy(this->wrapper);
 	}
 	this->this->lock->unlock(this->this->lock);
-
 	/* check for delayed certificate cache queue */
 	cache_queue(this->this);
 	free(this);
@@ -993,7 +995,7 @@ METHOD(enumerator_t, public_destroy, void,
 
 METHOD(credential_manager_t, create_public_enumerator, enumerator_t*,
 	private_credential_manager_t *this, key_type_t type, identification_t *id,
-	auth_cfg_t *auth)
+	auth_cfg_t *auth, bool online)
 {
 	public_enumerator_t *enumerator;
 
@@ -1002,7 +1004,7 @@ METHOD(credential_manager_t, create_public_enumerator, enumerator_t*,
 			.enumerate = (void*)_public_enumerate,
 			.destroy = _public_destroy,
 		},
-		.inner = create_trusted_enumerator(this, type, id, TRUE),
+		.inner = create_trusted_enumerator(this, type, id, online),
 		.this = this,
 	);
 	if (auth)
diff --git a/src/libstrongswan/credentials/credential_manager.h b/src/libstrongswan/credentials/credential_manager.h
index 445ea3f..022ca56 100644
--- a/src/libstrongswan/credentials/credential_manager.h
+++ b/src/libstrongswan/credentials/credential_manager.h
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2015 Tobias Brunner
  * Copyright (C) 2007-2009 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -202,14 +203,18 @@ struct credential_manager_t {
 	 * where the auth config helper contains rules for constraint checks.
 	 * This function is very similar to create_trusted_enumerator(), but
 	 * gets public keys directly.
+	 * If online is set, revocations are checked online for the whole
+	 * trustchain.
 	 *
 	 * @param type		type of the key to get
 	 * @param id		owner of the key, signer of the signature
 	 * @param auth		authentication infos
+	 * @param online	whether revocations should be checked online
 	 * @return			enumerator
 	 */
 	enumerator_t* (*create_public_enumerator)(credential_manager_t *this,
-					key_type_t type, identification_t *id, auth_cfg_t *auth);
+					key_type_t type, identification_t *id, auth_cfg_t *auth,
+					bool online);
 
 	/**
 	 * Cache a certificate by invoking cache_cert() on all registered sets.
diff --git a/src/libstrongswan/library.c b/src/libstrongswan/library.c
index dc73ccc..e130b93 100644
--- a/src/libstrongswan/library.c
+++ b/src/libstrongswan/library.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Tobias Brunner
+ * Copyright (C) 2009-2016 Tobias Brunner
  * Copyright (C) 2008 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -61,6 +61,31 @@ struct private_library_t {
 	refcount_t ref;
 };
 
+#define MAX_NAMESPACES 5
+
+/**
+ * Additional namespaces registered using __atrribute__((constructor))
+ */
+static char *namespaces[MAX_NAMESPACES];
+static int ns_count;
+
+/**
+ * Described in header
+ */
+void library_add_namespace(char *ns)
+{
+	if (ns_count < MAX_NAMESPACES - 1)
+	{
+		namespaces[ns_count] = ns;
+		ns_count++;
+	}
+	else
+	{
+		fprintf(stderr, "failed to register additional namespace alias, please "
+				"increase MAX_NAMESPACES");
+	}
+}
+
 /**
  * library instance
  */
@@ -248,6 +273,7 @@ bool library_init(char *settings, const char *namespace)
 {
 	private_library_t *this;
 	printf_hook_t *pfh;
+	int i;
 
 	if (lib)
 	{	/* already initialized, increase refcount */
@@ -311,6 +337,11 @@ bool library_init(char *settings, const char *namespace)
 									 (hashtable_equals_t)equals, 4);
 
 	this->public.settings = settings_create(this->public.conf);
+	/* add registered aliases */
+	for (i = 0; i < ns_count; ++i)
+	{
+		lib->settings->add_fallback(lib->settings, lib->ns, namespaces[i]);
+	}
 	/* all namespace settings may fall back to libstrongswan */
 	lib->settings->add_fallback(lib->settings, lib->ns, "libstrongswan");
 
diff --git a/src/libstrongswan/library.h b/src/libstrongswan/library.h
index 3a6dd1b..08316fd 100644
--- a/src/libstrongswan/library.h
+++ b/src/libstrongswan/library.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2014 Tobias Brunner
+ * Copyright (C) 2010-2016 Tobias Brunner
  * Copyright (C) 2008 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -276,4 +276,14 @@ void library_deinit();
  */
 extern library_t *lib;
 
+/**
+ * Add additional names used as alias for the namespace registered with
+ * library_init().
+ *
+ * To be called from __attribute__((constructor)) functions.
+ *
+ * @param ns			additional namespace
+ */
+void library_add_namespace(char *ns);
+
 #endif /** LIBRARY_H_ @}*/
diff --git a/src/libstrongswan/plugins/acert/Makefile.in b/src/libstrongswan/plugins/acert/Makefile.in
index 65542ea..034ab48 100644
--- a/src/libstrongswan/plugins/acert/Makefile.in
+++ b/src/libstrongswan/plugins/acert/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/aes/Makefile.in b/src/libstrongswan/plugins/aes/Makefile.in
index 9d79c81..6ad68a5 100644
--- a/src/libstrongswan/plugins/aes/Makefile.in
+++ b/src/libstrongswan/plugins/aes/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/aesni/Makefile.in b/src/libstrongswan/plugins/aesni/Makefile.in
index 34adaa3..7f91e43 100644
--- a/src/libstrongswan/plugins/aesni/Makefile.in
+++ b/src/libstrongswan/plugins/aesni/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/af_alg/Makefile.in b/src/libstrongswan/plugins/af_alg/Makefile.in
index 4a86f96..7aaea45 100644
--- a/src/libstrongswan/plugins/af_alg/Makefile.in
+++ b/src/libstrongswan/plugins/af_alg/Makefile.in
@@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/agent/Makefile.in b/src/libstrongswan/plugins/agent/Makefile.in
index 292c2fd..cbdc8e8 100644
--- a/src/libstrongswan/plugins/agent/Makefile.in
+++ b/src/libstrongswan/plugins/agent/Makefile.in
@@ -415,6 +415,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/bliss/Makefile.in b/src/libstrongswan/plugins/bliss/Makefile.in
index 1361dd3..8f91cdc 100644
--- a/src/libstrongswan/plugins/bliss/Makefile.in
+++ b/src/libstrongswan/plugins/bliss/Makefile.in
@@ -433,6 +433,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/bliss/tests/Makefile.in b/src/libstrongswan/plugins/bliss/tests/Makefile.in
index 5a1ce3d..43e508b 100644
--- a/src/libstrongswan/plugins/bliss/tests/Makefile.in
+++ b/src/libstrongswan/plugins/bliss/tests/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/blowfish/Makefile.in b/src/libstrongswan/plugins/blowfish/Makefile.in
index f196165..a6c3287 100644
--- a/src/libstrongswan/plugins/blowfish/Makefile.in
+++ b/src/libstrongswan/plugins/blowfish/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/ccm/Makefile.in b/src/libstrongswan/plugins/ccm/Makefile.in
index ca7cadb..3d56b98 100644
--- a/src/libstrongswan/plugins/ccm/Makefile.in
+++ b/src/libstrongswan/plugins/ccm/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/chapoly/Makefile.in b/src/libstrongswan/plugins/chapoly/Makefile.in
index 98e1f4d..b350658 100644
--- a/src/libstrongswan/plugins/chapoly/Makefile.in
+++ b/src/libstrongswan/plugins/chapoly/Makefile.in
@@ -428,6 +428,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/chapoly/chapoly_drv_portable.c b/src/libstrongswan/plugins/chapoly/chapoly_drv_portable.c
index 54e934e..dfed4d5 100644
--- a/src/libstrongswan/plugins/chapoly/chapoly_drv_portable.c
+++ b/src/libstrongswan/plugins/chapoly/chapoly_drv_portable.c
@@ -58,27 +58,6 @@ struct private_chapoly_drv_portable_t {
 };
 
 /**
- * Convert unaligned little endian to host byte order
- */
-static inline u_int32_t uletoh32(void *p)
-{
-	u_int32_t ret;
-
-	memcpy(&ret, p, sizeof(ret));
-	ret = le32toh(ret);
-	return ret;
-}
-
-/**
- * Convert host byte order to unaligned little endian
- */
-static inline void htoule32(void *p, u_int32_t v)
-{
-	v = htole32(v);
-	memcpy(p, &v, sizeof(v));
-}
-
-/**
  * XOR a 32-bit integer into an unaligned destination
  */
 static inline void xor32u(void *p, u_int32_t x)
diff --git a/src/libstrongswan/plugins/cmac/Makefile.in b/src/libstrongswan/plugins/cmac/Makefile.in
index 9e24939..2ffaa06 100644
--- a/src/libstrongswan/plugins/cmac/Makefile.in
+++ b/src/libstrongswan/plugins/cmac/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/constraints/Makefile.in b/src/libstrongswan/plugins/constraints/Makefile.in
index 2e623ad..f263f77 100644
--- a/src/libstrongswan/plugins/constraints/Makefile.in
+++ b/src/libstrongswan/plugins/constraints/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/ctr/Makefile.in b/src/libstrongswan/plugins/ctr/Makefile.in
index 7b7231b..9558f87 100644
--- a/src/libstrongswan/plugins/ctr/Makefile.in
+++ b/src/libstrongswan/plugins/ctr/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/curl/Makefile.in b/src/libstrongswan/plugins/curl/Makefile.in
index d525eac..8fc366c 100644
--- a/src/libstrongswan/plugins/curl/Makefile.in
+++ b/src/libstrongswan/plugins/curl/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/des/Makefile.in b/src/libstrongswan/plugins/des/Makefile.in
index 96b2f60..6a09d63 100644
--- a/src/libstrongswan/plugins/des/Makefile.in
+++ b/src/libstrongswan/plugins/des/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/dnskey/Makefile.in b/src/libstrongswan/plugins/dnskey/Makefile.in
index 9102899..55ebb34 100644
--- a/src/libstrongswan/plugins/dnskey/Makefile.in
+++ b/src/libstrongswan/plugins/dnskey/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/files/Makefile.in b/src/libstrongswan/plugins/files/Makefile.in
index 31dc4a3..6c2e792 100644
--- a/src/libstrongswan/plugins/files/Makefile.in
+++ b/src/libstrongswan/plugins/files/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/fips_prf/Makefile.in b/src/libstrongswan/plugins/fips_prf/Makefile.in
index b7ca1ce..252035c 100644
--- a/src/libstrongswan/plugins/fips_prf/Makefile.in
+++ b/src/libstrongswan/plugins/fips_prf/Makefile.in
@@ -415,6 +415,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/gcm/Makefile.in b/src/libstrongswan/plugins/gcm/Makefile.in
index e125ab8..f9c4a69 100644
--- a/src/libstrongswan/plugins/gcm/Makefile.in
+++ b/src/libstrongswan/plugins/gcm/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/gcrypt/Makefile.in b/src/libstrongswan/plugins/gcrypt/Makefile.in
index 4ce7438..774c447 100644
--- a/src/libstrongswan/plugins/gcrypt/Makefile.in
+++ b/src/libstrongswan/plugins/gcrypt/Makefile.in
@@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
index 04f1f43..7ecba8f 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
@@ -98,14 +98,14 @@ METHOD(plugin_t, get_features, int,
 			PLUGIN_PROVIDE(HASHER, HASH_SHA512),
 		/* MODP DH groups */
 		PLUGIN_REGISTER(DH, gcrypt_dh_create),
-			PLUGIN_PROVIDE(DH, MODP_2048_BIT),
-			PLUGIN_PROVIDE(DH, MODP_2048_224),
-			PLUGIN_PROVIDE(DH, MODP_2048_256),
-			PLUGIN_PROVIDE(DH, MODP_1536_BIT),
 			PLUGIN_PROVIDE(DH, MODP_3072_BIT),
 			PLUGIN_PROVIDE(DH, MODP_4096_BIT),
 			PLUGIN_PROVIDE(DH, MODP_6144_BIT),
 			PLUGIN_PROVIDE(DH, MODP_8192_BIT),
+			PLUGIN_PROVIDE(DH, MODP_2048_BIT),
+			PLUGIN_PROVIDE(DH, MODP_2048_224),
+			PLUGIN_PROVIDE(DH, MODP_2048_256),
+			PLUGIN_PROVIDE(DH, MODP_1536_BIT),
 			PLUGIN_PROVIDE(DH, MODP_1024_BIT),
 			PLUGIN_PROVIDE(DH, MODP_1024_160),
 			PLUGIN_PROVIDE(DH, MODP_768_BIT),
diff --git a/src/libstrongswan/plugins/gmp/Makefile.in b/src/libstrongswan/plugins/gmp/Makefile.in
index 788cb93..9a2d301 100644
--- a/src/libstrongswan/plugins/gmp/Makefile.in
+++ b/src/libstrongswan/plugins/gmp/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/gmp/gmp_plugin.c b/src/libstrongswan/plugins/gmp/gmp_plugin.c
index d93aa14..ea75896 100644
--- a/src/libstrongswan/plugins/gmp/gmp_plugin.c
+++ b/src/libstrongswan/plugins/gmp/gmp_plugin.c
@@ -45,14 +45,6 @@ METHOD(plugin_t, get_features, int,
 	static plugin_feature_t f[] = {
 		/* DH groups */
 		PLUGIN_REGISTER(DH, gmp_diffie_hellman_create),
-			PLUGIN_PROVIDE(DH, MODP_2048_BIT),
-				PLUGIN_DEPENDS(RNG, RNG_STRONG),
-			PLUGIN_PROVIDE(DH, MODP_2048_224),
-				PLUGIN_DEPENDS(RNG, RNG_STRONG),
-			PLUGIN_PROVIDE(DH, MODP_2048_256),
-				PLUGIN_DEPENDS(RNG, RNG_STRONG),
-			PLUGIN_PROVIDE(DH, MODP_1536_BIT),
-				PLUGIN_DEPENDS(RNG, RNG_STRONG),
 			PLUGIN_PROVIDE(DH, MODP_3072_BIT),
 				PLUGIN_DEPENDS(RNG, RNG_STRONG),
 			PLUGIN_PROVIDE(DH, MODP_4096_BIT),
@@ -61,6 +53,14 @@ METHOD(plugin_t, get_features, int,
 				PLUGIN_DEPENDS(RNG, RNG_STRONG),
 			PLUGIN_PROVIDE(DH, MODP_8192_BIT),
 				PLUGIN_DEPENDS(RNG, RNG_STRONG),
+			PLUGIN_PROVIDE(DH, MODP_2048_BIT),
+				PLUGIN_DEPENDS(RNG, RNG_STRONG),
+			PLUGIN_PROVIDE(DH, MODP_2048_224),
+				PLUGIN_DEPENDS(RNG, RNG_STRONG),
+			PLUGIN_PROVIDE(DH, MODP_2048_256),
+				PLUGIN_DEPENDS(RNG, RNG_STRONG),
+			PLUGIN_PROVIDE(DH, MODP_1536_BIT),
+				PLUGIN_DEPENDS(RNG, RNG_STRONG),
 			PLUGIN_PROVIDE(DH, MODP_1024_BIT),
 				PLUGIN_DEPENDS(RNG, RNG_STRONG),
 			PLUGIN_PROVIDE(DH, MODP_1024_160),
diff --git a/src/libstrongswan/plugins/hmac/Makefile.in b/src/libstrongswan/plugins/hmac/Makefile.in
index a8c39cb..46fac4a 100644
--- a/src/libstrongswan/plugins/hmac/Makefile.in
+++ b/src/libstrongswan/plugins/hmac/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/keychain/Makefile.in b/src/libstrongswan/plugins/keychain/Makefile.in
index 8f6a6f5..eb0bdf3 100644
--- a/src/libstrongswan/plugins/keychain/Makefile.in
+++ b/src/libstrongswan/plugins/keychain/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/ldap/Makefile.in b/src/libstrongswan/plugins/ldap/Makefile.in
index 5316323..0a03fd8 100644
--- a/src/libstrongswan/plugins/ldap/Makefile.in
+++ b/src/libstrongswan/plugins/ldap/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/md4/Makefile.in b/src/libstrongswan/plugins/md4/Makefile.in
index d5f9c6c..4dbdbe0 100644
--- a/src/libstrongswan/plugins/md4/Makefile.in
+++ b/src/libstrongswan/plugins/md4/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/md5/Makefile.in b/src/libstrongswan/plugins/md5/Makefile.in
index 1dd3892..6fc25b0 100644
--- a/src/libstrongswan/plugins/md5/Makefile.in
+++ b/src/libstrongswan/plugins/md5/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/mysql/Makefile.in b/src/libstrongswan/plugins/mysql/Makefile.in
index e2fb7e7..17409db 100644
--- a/src/libstrongswan/plugins/mysql/Makefile.in
+++ b/src/libstrongswan/plugins/mysql/Makefile.in
@@ -415,6 +415,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/nonce/Makefile.in b/src/libstrongswan/plugins/nonce/Makefile.in
index 0b51ba5..68be3f4 100644
--- a/src/libstrongswan/plugins/nonce/Makefile.in
+++ b/src/libstrongswan/plugins/nonce/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/ntru/Makefile.in b/src/libstrongswan/plugins/ntru/Makefile.in
index 5636692..97a7067 100644
--- a/src/libstrongswan/plugins/ntru/Makefile.in
+++ b/src/libstrongswan/plugins/ntru/Makefile.in
@@ -415,6 +415,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/openssl/Makefile.in b/src/libstrongswan/plugins/openssl/Makefile.in
index a667ca4..3020169 100644
--- a/src/libstrongswan/plugins/openssl/Makefile.in
+++ b/src/libstrongswan/plugins/openssl/Makefile.in
@@ -423,6 +423,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c
index e48efe3..aeb9be4 100644
--- a/src/libstrongswan/plugins/openssl/openssl_plugin.c
+++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c
@@ -365,28 +365,41 @@ METHOD(plugin_t, get_features, int,
 #ifndef OPENSSL_NO_AES
 		/* AES GCM */
 		PLUGIN_REGISTER(AEAD, openssl_gcm_create),
-			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 16),
-			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 24),
-			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 32),
-			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 16),
-			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 24),
-			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 32),
 			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 16),
 			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 24),
 			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 32),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 16),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 24),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 32),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8,  16),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8,  24),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8,  32),
 #endif /* OPENSSL_NO_AES */
 #endif /* OPENSSL_VERSION_NUMBER */
+#ifndef OPENSSL_NO_ECDH
+		/* EC DH groups */
+		PLUGIN_REGISTER(DH, openssl_ec_diffie_hellman_create),
+			PLUGIN_PROVIDE(DH, ECP_256_BIT),
+			PLUGIN_PROVIDE(DH, ECP_384_BIT),
+			PLUGIN_PROVIDE(DH, ECP_521_BIT),
+			PLUGIN_PROVIDE(DH, ECP_224_BIT),
+			PLUGIN_PROVIDE(DH, ECP_192_BIT),
+			PLUGIN_PROVIDE(DH, ECP_256_BP),
+			PLUGIN_PROVIDE(DH, ECP_384_BP),
+			PLUGIN_PROVIDE(DH, ECP_512_BP),
+			PLUGIN_PROVIDE(DH, ECP_224_BP),
+#endif
 #ifndef OPENSSL_NO_DH
 		/* MODP DH groups */
 		PLUGIN_REGISTER(DH, openssl_diffie_hellman_create),
-			PLUGIN_PROVIDE(DH, MODP_2048_BIT),
-			PLUGIN_PROVIDE(DH, MODP_2048_224),
-			PLUGIN_PROVIDE(DH, MODP_2048_256),
-			PLUGIN_PROVIDE(DH, MODP_1536_BIT),
 			PLUGIN_PROVIDE(DH, MODP_3072_BIT),
 			PLUGIN_PROVIDE(DH, MODP_4096_BIT),
 			PLUGIN_PROVIDE(DH, MODP_6144_BIT),
 			PLUGIN_PROVIDE(DH, MODP_8192_BIT),
+			PLUGIN_PROVIDE(DH, MODP_2048_BIT),
+			PLUGIN_PROVIDE(DH, MODP_2048_224),
+			PLUGIN_PROVIDE(DH, MODP_2048_256),
+			PLUGIN_PROVIDE(DH, MODP_1536_BIT),
 			PLUGIN_PROVIDE(DH, MODP_1024_BIT),
 			PLUGIN_PROVIDE(DH, MODP_1024_160),
 			PLUGIN_PROVIDE(DH, MODP_768_BIT),
@@ -446,19 +459,6 @@ METHOD(plugin_t, get_features, int,
 #endif /* OPENSSL_VERSION_NUMBER */
 		PLUGIN_REGISTER(CONTAINER_DECODE, openssl_pkcs12_load, TRUE),
 			PLUGIN_PROVIDE(CONTAINER_DECODE, CONTAINER_PKCS12),
-#ifndef OPENSSL_NO_ECDH
-		/* EC DH groups */
-		PLUGIN_REGISTER(DH, openssl_ec_diffie_hellman_create),
-			PLUGIN_PROVIDE(DH, ECP_256_BIT),
-			PLUGIN_PROVIDE(DH, ECP_384_BIT),
-			PLUGIN_PROVIDE(DH, ECP_521_BIT),
-			PLUGIN_PROVIDE(DH, ECP_224_BIT),
-			PLUGIN_PROVIDE(DH, ECP_192_BIT),
-			PLUGIN_PROVIDE(DH, ECP_224_BP),
-			PLUGIN_PROVIDE(DH, ECP_256_BP),
-			PLUGIN_PROVIDE(DH, ECP_384_BP),
-			PLUGIN_PROVIDE(DH, ECP_512_BP),
-#endif
 #ifndef OPENSSL_NO_ECDSA
 		/* EC private/public key loading */
 		PLUGIN_REGISTER(PRIVKEY, openssl_ec_private_key_load, TRUE),
diff --git a/src/libstrongswan/plugins/padlock/Makefile.in b/src/libstrongswan/plugins/padlock/Makefile.in
index 44603af..2d6006b 100644
--- a/src/libstrongswan/plugins/padlock/Makefile.in
+++ b/src/libstrongswan/plugins/padlock/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/pem/Makefile.in b/src/libstrongswan/plugins/pem/Makefile.in
index 4c982fd..16dfbed 100644
--- a/src/libstrongswan/plugins/pem/Makefile.in
+++ b/src/libstrongswan/plugins/pem/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/pgp/Makefile.in b/src/libstrongswan/plugins/pgp/Makefile.in
index 4d4215b..a558779 100644
--- a/src/libstrongswan/plugins/pgp/Makefile.in
+++ b/src/libstrongswan/plugins/pgp/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/pkcs1/Makefile.in b/src/libstrongswan/plugins/pkcs1/Makefile.in
index 2a70836..a265818 100644
--- a/src/libstrongswan/plugins/pkcs1/Makefile.in
+++ b/src/libstrongswan/plugins/pkcs1/Makefile.in
@@ -415,6 +415,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/pkcs11/Makefile.in b/src/libstrongswan/plugins/pkcs11/Makefile.in
index de033a3..f4bded4 100644
--- a/src/libstrongswan/plugins/pkcs11/Makefile.in
+++ b/src/libstrongswan/plugins/pkcs11/Makefile.in
@@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/pkcs12/Makefile.in b/src/libstrongswan/plugins/pkcs12/Makefile.in
index 3fa0a38..7fd3158 100644
--- a/src/libstrongswan/plugins/pkcs12/Makefile.in
+++ b/src/libstrongswan/plugins/pkcs12/Makefile.in
@@ -415,6 +415,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/pkcs7/Makefile.in b/src/libstrongswan/plugins/pkcs7/Makefile.in
index 3266e5d..5fc439b 100644
--- a/src/libstrongswan/plugins/pkcs7/Makefile.in
+++ b/src/libstrongswan/plugins/pkcs7/Makefile.in
@@ -417,6 +417,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/pkcs8/Makefile.in b/src/libstrongswan/plugins/pkcs8/Makefile.in
index 2130c9c..162868a 100644
--- a/src/libstrongswan/plugins/pkcs8/Makefile.in
+++ b/src/libstrongswan/plugins/pkcs8/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/pubkey/Makefile.in b/src/libstrongswan/plugins/pubkey/Makefile.in
index a9f3dd1..007bdbd 100644
--- a/src/libstrongswan/plugins/pubkey/Makefile.in
+++ b/src/libstrongswan/plugins/pubkey/Makefile.in
@@ -415,6 +415,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/pubkey/pubkey_cert.c b/src/libstrongswan/plugins/pubkey/pubkey_cert.c
index b7ba5ad..0631a68 100644
--- a/src/libstrongswan/plugins/pubkey/pubkey_cert.c
+++ b/src/libstrongswan/plugins/pubkey/pubkey_cert.c
@@ -196,6 +196,13 @@ METHOD(certificate_t, destroy, void,
 	}
 }
 
+METHOD(pubkey_cert_t, set_subject, void,
+	private_pubkey_cert_t *this, identification_t *subject)
+{
+	DESTROY_IF(this->subject);
+	this->subject = subject->clone(subject);
+}
+
 /*
  * see header file
  */
@@ -222,6 +229,7 @@ static pubkey_cert_t *pubkey_cert_create(public_key_t *key,
 				.get_ref = _get_ref,
 				.destroy = _destroy,
 			},
+			.set_subject = _set_subject,
 		},
 		.ref = 1,
 		.key = key,
diff --git a/src/libstrongswan/plugins/pubkey/pubkey_cert.h b/src/libstrongswan/plugins/pubkey/pubkey_cert.h
index a2d7353..06e4e0f 100644
--- a/src/libstrongswan/plugins/pubkey/pubkey_cert.h
+++ b/src/libstrongswan/plugins/pubkey/pubkey_cert.h
@@ -35,6 +35,13 @@ struct pubkey_cert_t {
 	 * Implements certificate_t.
 	 */
 	certificate_t interface;
+
+	/**
+	 * Set the subject of the trusted public key.
+	 *
+	 * @param subject	subject to be set
+	 */
+	void (*set_subject)(pubkey_cert_t *this, identification_t *subject);
 };
 
 /**
diff --git a/src/libstrongswan/plugins/random/Makefile.in b/src/libstrongswan/plugins/random/Makefile.in
index 11a1346..f6dc73e 100644
--- a/src/libstrongswan/plugins/random/Makefile.in
+++ b/src/libstrongswan/plugins/random/Makefile.in
@@ -415,6 +415,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/rc2/Makefile.in b/src/libstrongswan/plugins/rc2/Makefile.in
index b81acef..b9fc8bd 100644
--- a/src/libstrongswan/plugins/rc2/Makefile.in
+++ b/src/libstrongswan/plugins/rc2/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/rdrand/Makefile.in b/src/libstrongswan/plugins/rdrand/Makefile.in
index 028464b..f6bdf9c 100644
--- a/src/libstrongswan/plugins/rdrand/Makefile.in
+++ b/src/libstrongswan/plugins/rdrand/Makefile.in
@@ -415,6 +415,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/revocation/Makefile.in b/src/libstrongswan/plugins/revocation/Makefile.in
index 342c544..4c7f272 100644
--- a/src/libstrongswan/plugins/revocation/Makefile.in
+++ b/src/libstrongswan/plugins/revocation/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/sha1/Makefile.in b/src/libstrongswan/plugins/sha1/Makefile.in
index 18771e4..1de07d7 100644
--- a/src/libstrongswan/plugins/sha1/Makefile.in
+++ b/src/libstrongswan/plugins/sha1/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/sha2/Makefile.in b/src/libstrongswan/plugins/sha2/Makefile.in
index 6aaa06b..d4af8fb 100644
--- a/src/libstrongswan/plugins/sha2/Makefile.in
+++ b/src/libstrongswan/plugins/sha2/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/sha3/Makefile.in b/src/libstrongswan/plugins/sha3/Makefile.in
index 3034ea5..9aa58e2 100644
--- a/src/libstrongswan/plugins/sha3/Makefile.in
+++ b/src/libstrongswan/plugins/sha3/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/soup/Makefile.in b/src/libstrongswan/plugins/soup/Makefile.in
index 02290b4..acb05d5 100644
--- a/src/libstrongswan/plugins/soup/Makefile.in
+++ b/src/libstrongswan/plugins/soup/Makefile.in
@@ -414,6 +414,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/sqlite/Makefile.in b/src/libstrongswan/plugins/sqlite/Makefile.in
index 3e234f1..ca59bb7 100644
--- a/src/libstrongswan/plugins/sqlite/Makefile.in
+++ b/src/libstrongswan/plugins/sqlite/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/sshkey/Makefile.in b/src/libstrongswan/plugins/sshkey/Makefile.in
index a8d5a10..feb9313 100644
--- a/src/libstrongswan/plugins/sshkey/Makefile.in
+++ b/src/libstrongswan/plugins/sshkey/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/test_vectors/Makefile.in b/src/libstrongswan/plugins/test_vectors/Makefile.in
index 100f3b1..431b607 100644
--- a/src/libstrongswan/plugins/test_vectors/Makefile.in
+++ b/src/libstrongswan/plugins/test_vectors/Makefile.in
@@ -432,6 +432,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/unbound/Makefile.in b/src/libstrongswan/plugins/unbound/Makefile.in
index c84717b..59590d1 100644
--- a/src/libstrongswan/plugins/unbound/Makefile.in
+++ b/src/libstrongswan/plugins/unbound/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/winhttp/Makefile.in b/src/libstrongswan/plugins/winhttp/Makefile.in
index f8db1ff..acfc57b 100644
--- a/src/libstrongswan/plugins/winhttp/Makefile.in
+++ b/src/libstrongswan/plugins/winhttp/Makefile.in
@@ -416,6 +416,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/x509/Makefile.in b/src/libstrongswan/plugins/x509/Makefile.in
index b31bfbe..c58dfe2 100644
--- a/src/libstrongswan/plugins/x509/Makefile.in
+++ b/src/libstrongswan/plugins/x509/Makefile.in
@@ -415,6 +415,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c
index 96280a0..2b83f33 100644
--- a/src/libstrongswan/plugins/x509/x509_cert.c
+++ b/src/libstrongswan/plugins/x509/x509_cert.c
@@ -2143,8 +2143,8 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
 		msSmartcardLogon = asn1_build_known_oid(OID_MS_SMARTCARD_LOGON);
 	}
 
-	if (serverAuth.ptr || clientAuth.ptr || ikeIntermediate.ptr ||
-		ocspSigning.ptr)
+	if (serverAuth.ptr  || clientAuth.ptr || ikeIntermediate.ptr ||
+		ocspSigning.ptr || msSmartcardLogon.ptr)
 	{
 		extendedKeyUsage = asn1_wrap(ASN1_SEQUENCE, "mm",
 								asn1_build_known_oid(OID_EXTENDED_KEY_USAGE),
diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_response.c b/src/libstrongswan/plugins/x509/x509_ocsp_response.c
index 60133fc..b46af30 100644
--- a/src/libstrongswan/plugins/x509/x509_ocsp_response.c
+++ b/src/libstrongswan/plugins/x509/x509_ocsp_response.c
@@ -1,7 +1,8 @@
 /**
  * Copyright (C) 2008-2009 Martin Willi
- * Copyright (C) 2007-2014 Andreas Steffen
- * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2007-2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
  * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -228,6 +229,42 @@ METHOD(ocsp_response_t, create_cert_enumerator, enumerator_t*,
 }
 
 /**
+ * enumerator filter callback for create_response_enumerator
+ */
+static bool filter(void *data, single_response_t **response,
+				   chunk_t *serialNumber,
+				   void *p2, cert_validation_t *status,
+				   void *p3, time_t *revocationTime,
+				   void *p4, crl_reason_t *revocationReason)
+{
+	if (serialNumber)
+	{
+		*serialNumber = (*response)->serialNumber;
+	}
+	if (status)
+	{
+		*status = (*response)->status;
+	}
+	if (revocationTime)
+	{
+		*revocationTime = (*response)->revocationTime;
+	}
+	if (revocationReason)
+	{
+		*revocationReason = (*response)->revocationReason;
+	}
+	return TRUE;
+}
+
+METHOD(ocsp_response_t, create_response_enumerator, enumerator_t*,
+	private_x509_ocsp_response_t *this)
+{
+	return enumerator_create_filter(
+				this->responses->create_enumerator(this->responses),
+				(void*)filter, NULL, NULL);
+}
+
+/**
  * ASN.1 definition of singleResponse
  */
 static const asn1Object_t singleResponseObjects[] = {
@@ -828,6 +865,7 @@ static x509_ocsp_response_t *load(chunk_t blob)
 				},
 				.get_status = _get_status,
 				.create_cert_enumerator = _create_cert_enumerator,
+				.create_response_enumerator = _create_response_enumerator,
 			},
 		},
 		.ref = 1,
diff --git a/src/libstrongswan/plugins/xcbc/Makefile.in b/src/libstrongswan/plugins/xcbc/Makefile.in
index 6c9901e..6f69fb1 100644
--- a/src/libstrongswan/plugins/xcbc/Makefile.in
+++ b/src/libstrongswan/plugins/xcbc/Makefile.in
@@ -413,6 +413,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libstrongswan/processing/watcher.c b/src/libstrongswan/processing/watcher.c
index 5b94208..b762850 100644
--- a/src/libstrongswan/processing/watcher.c
+++ b/src/libstrongswan/processing/watcher.c
@@ -345,6 +345,13 @@ static job_requeue_t watch(private_watcher_t *this)
 		old = thread_cancelability(TRUE);
 
 		res = poll(pfd, count, -1);
+		if (res == -1 && errno == EINTR)
+		{
+			/* LinuxThreads interrupts poll(), but does not make it a
+			 * cancellation point. Manually test if we got cancelled. */
+			thread_cancellation_point();
+		}
+
 		thread_cancelability(old);
 		thread_cleanup_pop(FALSE);
 
diff --git a/src/libstrongswan/tests/Makefile.am b/src/libstrongswan/tests/Makefile.am
index d86584a..b2d4560 100644
--- a/src/libstrongswan/tests/Makefile.am
+++ b/src/libstrongswan/tests/Makefile.am
@@ -44,6 +44,7 @@ tests_SOURCES = tests.h tests.c \
   suites/test_certpolicy.c \
   suites/test_certnames.c \
   suites/test_host.c \
+  suites/test_auth_cfg.c \
   suites/test_hasher.c \
   suites/test_crypter.c \
   suites/test_crypto_factory.c \
diff --git a/src/libstrongswan/tests/Makefile.in b/src/libstrongswan/tests/Makefile.in
index 13fd4cc..0a0f589 100644
--- a/src/libstrongswan/tests/Makefile.in
+++ b/src/libstrongswan/tests/Makefile.in
@@ -140,6 +140,7 @@ am_tests_OBJECTS = tests-tests.$(OBJEXT) \
 	suites/tests-test_certpolicy.$(OBJEXT) \
 	suites/tests-test_certnames.$(OBJEXT) \
 	suites/tests-test_host.$(OBJEXT) \
+	suites/tests-test_auth_cfg.$(OBJEXT) \
 	suites/tests-test_hasher.$(OBJEXT) \
 	suites/tests-test_crypter.$(OBJEXT) \
 	suites/tests-test_crypto_factory.$(OBJEXT) \
@@ -452,6 +453,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -505,6 +508,7 @@ tests_SOURCES = tests.h tests.c \
   suites/test_certpolicy.c \
   suites/test_certnames.c \
   suites/test_host.c \
+  suites/test_auth_cfg.c \
   suites/test_hasher.c \
   suites/test_crypter.c \
   suites/test_crypto_factory.c \
@@ -648,6 +652,8 @@ suites/tests-test_certnames.$(OBJEXT): suites/$(am__dirstamp) \
 	suites/$(DEPDIR)/$(am__dirstamp)
 suites/tests-test_host.$(OBJEXT): suites/$(am__dirstamp) \
 	suites/$(DEPDIR)/$(am__dirstamp)
+suites/tests-test_auth_cfg.$(OBJEXT): suites/$(am__dirstamp) \
+	suites/$(DEPDIR)/$(am__dirstamp)
 suites/tests-test_hasher.$(OBJEXT): suites/$(am__dirstamp) \
 	suites/$(DEPDIR)/$(am__dirstamp)
 suites/tests-test_crypter.$(OBJEXT): suites/$(am__dirstamp) \
@@ -690,6 +696,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/tests-test_array.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/tests-test_asn1.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/tests-test_asn1_parser.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/tests-test_auth_cfg.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/tests-test_bio_reader.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/tests-test_bio_writer.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/tests-test_certnames.Po at am__quote@
@@ -1119,6 +1126,20 @@ suites/tests-test_host.obj: suites/test_host.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o suites/tests-test_host.obj `if test -f 'suites/test_host.c'; then $(CYGPATH_W) 'suites/test_host.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_host.c'; fi`
 
+suites/tests-test_auth_cfg.o: suites/test_auth_cfg.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT suites/tests-test_auth_cfg.o -MD -MP -MF suites/$(DEPDIR)/tests-test_auth_cfg.Tpo -c -o suites/tests-test_auth_cfg.o `test -f 'suites/test_auth_cfg.c' || echo '$(srcdir)/'`suites/test_auth_cfg.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/tests-test_auth_cfg.Tpo suites/$(DEPDIR)/tests-test_auth_cfg.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_auth_cfg.c' object='suites/tests-test_auth_cfg.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o suites/tests-test_auth_cfg.o `test -f 'suites/test_auth_cfg.c' || echo '$(srcdir)/'`suites/test_auth_cfg.c
+
+suites/tests-test_auth_cfg.obj: suites/test_auth_cfg.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT suites/tests-test_auth_cfg.obj -MD -MP -MF suites/$(DEPDIR)/tests-test_auth_cfg.Tpo -c -o suites/tests-test_auth_cfg.obj `if test -f 'suites/test_auth_cfg.c'; then $(CYGPATH_W) 'suites/test_auth_cfg.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_auth_cfg.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/tests-test_auth_cfg.Tpo suites/$(DEPDIR)/tests-test_auth_cfg.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_auth_cfg.c' object='suites/tests-test_auth_cfg.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -c -o suites/tests-test_auth_cfg.obj `if test -f 'suites/test_auth_cfg.c'; then $(CYGPATH_W) 'suites/test_auth_cfg.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_auth_cfg.c'; fi`
+
 suites/tests-test_hasher.o: suites/test_hasher.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT suites/tests-test_hasher.o -MD -MP -MF suites/$(DEPDIR)/tests-test_hasher.Tpo -c -o suites/tests-test_hasher.o `test -f 'suites/test_hasher.c' || echo '$(srcdir)/'`suites/test_hasher.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/tests-test_hasher.Tpo suites/$(DEPDIR)/tests-test_hasher.Po
diff --git a/src/libstrongswan/tests/suites/test_array.c b/src/libstrongswan/tests/suites/test_array.c
index ba2aff4..eda72e1 100644
--- a/src/libstrongswan/tests/suites/test_array.c
+++ b/src/libstrongswan/tests/suites/test_array.c
@@ -491,6 +491,44 @@ START_TEST(test_invoke_offset)
 }
 END_TEST
 
+START_TEST(test_insert_create)
+{
+	array_t *array = NULL;
+	uintptr_t x;
+
+	array_insert_create(&array, ARRAY_TAIL, (void*)(uintptr_t)1);
+	array_insert_create(&array, ARRAY_TAIL, (void*)(uintptr_t)2);
+	ck_assert(array != NULL);
+
+	ck_assert(array_get(array, ARRAY_HEAD, &x));
+	ck_assert_int_eq(x, 1);
+	ck_assert(array_get(array, ARRAY_TAIL, &x));
+	ck_assert_int_eq(x, 2);
+
+	array_destroy(array);
+}
+END_TEST
+
+START_TEST(test_insert_create_value)
+{
+	array_t *array = NULL;
+	u_int16_t v;
+
+	v = 1;
+	array_insert_create_value(&array, sizeof(v), ARRAY_TAIL, &v);
+	v = 2;
+	array_insert_create_value(&array, sizeof(v), ARRAY_TAIL, &v);
+	ck_assert(array != NULL);
+
+	ck_assert(array_get(array, ARRAY_HEAD, &v));
+	ck_assert_int_eq(v, 1);
+	ck_assert(array_get(array, ARRAY_TAIL, &v));
+	ck_assert_int_eq(v, 2);
+
+	array_destroy(array);
+}
+END_TEST
+
 Suite *array_suite_create()
 {
 	Suite *s;
@@ -528,5 +566,10 @@ Suite *array_suite_create()
 	tcase_add_test(tc, test_invoke_offset);
 	suite_add_tcase(s, tc);
 
+	tc = tcase_create("insert create");
+	tcase_add_test(tc, test_insert_create);
+	tcase_add_test(tc, test_insert_create_value);
+	suite_add_tcase(s, tc);
+
 	return s;
 }
diff --git a/src/libstrongswan/tests/suites/test_auth_cfg.c b/src/libstrongswan/tests/suites/test_auth_cfg.c
new file mode 100644
index 0000000..e046725
--- /dev/null
+++ b/src/libstrongswan/tests/suites/test_auth_cfg.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include "test_suite.h"
+
+#include <credentials/auth_cfg.h>
+
+struct {
+	char *constraints;
+	signature_scheme_t sig[5];
+	signature_scheme_t ike[5];
+} sig_constraints_tests[] = {
+	{ "rsa-sha256", { SIGN_RSA_EMSA_PKCS1_SHA256, 0 }, {0}},
+	{ "rsa-sha256-sha512", { SIGN_RSA_EMSA_PKCS1_SHA256, SIGN_RSA_EMSA_PKCS1_SHA512, 0 }, {0}},
+	{ "ecdsa-sha256", { SIGN_ECDSA_WITH_SHA256_DER, SIGN_ECDSA_256, 0 }, {0}},
+	{ "rsa-sha256-ecdsa-sha256", { SIGN_RSA_EMSA_PKCS1_SHA256, SIGN_ECDSA_WITH_SHA256_DER, SIGN_ECDSA_256, 0 }, {0}},
+	{ "pubkey-sha256", { SIGN_RSA_EMSA_PKCS1_SHA256, SIGN_ECDSA_WITH_SHA256_DER, SIGN_ECDSA_256, SIGN_BLISS_WITH_SHA2_256, 0 }, {0}},
+	{ "ike:rsa-sha256", {0}, { SIGN_RSA_EMSA_PKCS1_SHA256, 0 }},
+	{ "ike:rsa-sha256-rsa-sha256", { SIGN_RSA_EMSA_PKCS1_SHA256, 0 }, { SIGN_RSA_EMSA_PKCS1_SHA256, 0 }},
+	{ "rsa-sha256-ike:rsa-sha256", { SIGN_RSA_EMSA_PKCS1_SHA256, 0 }, { SIGN_RSA_EMSA_PKCS1_SHA256, 0 }},
+	{ "ike:pubkey-sha256", {0}, { SIGN_RSA_EMSA_PKCS1_SHA256, SIGN_ECDSA_WITH_SHA256_DER, SIGN_ECDSA_256, SIGN_BLISS_WITH_SHA2_256, 0 }},
+	{ "rsa-ecdsa-sha256", { SIGN_ECDSA_WITH_SHA256_DER, SIGN_ECDSA_256, 0 }, {0}},
+	{ "rsa-4096-ecdsa-sha256", { SIGN_ECDSA_WITH_SHA256_DER, SIGN_ECDSA_256, 0 }, {0}},
+	{ "rsa-4096-ecdsa-256-sha256", { SIGN_ECDSA_WITH_SHA256_DER, SIGN_ECDSA_256, 0 }, {0}},
+	{ "rsa-ecdsa256-sha256", { SIGN_RSA_EMSA_PKCS1_SHA256, 0 }, {0}},
+	{ "rsa4096-sha256", {0}, {0}},
+	{ "sha256", {0}, {0}},
+	{ "ike:sha256", {0}, {0}},
+};
+
+static void check_sig_constraints(auth_cfg_t *cfg, auth_rule_t type,
+								  signature_scheme_t expected[])
+{
+	enumerator_t *enumerator;
+	auth_rule_t t;
+	void *value;
+	int i = 0;
+
+	enumerator = cfg->create_enumerator(cfg);
+	while (enumerator->enumerate(enumerator, &t, &value))
+	{
+		if (t == type)
+		{
+			ck_assert(expected[i]);
+			ck_assert_int_eq(expected[i], (signature_scheme_t)value);
+			i++;
+		}
+	}
+	enumerator->destroy(enumerator);
+	ck_assert(!expected[i]);
+}
+
+START_TEST(test_sig_contraints)
+{
+	auth_cfg_t *cfg;
+	signature_scheme_t none[] = {0};
+
+	cfg = auth_cfg_create();
+	cfg->add_pubkey_constraints(cfg, sig_constraints_tests[_i].constraints, FALSE);
+	check_sig_constraints(cfg, AUTH_RULE_SIGNATURE_SCHEME, sig_constraints_tests[_i].sig);
+	check_sig_constraints(cfg, AUTH_RULE_IKE_SIGNATURE_SCHEME, none);
+	cfg->destroy(cfg);
+
+	lib->settings->set_bool(lib->settings, "%s.signature_authentication_constraints",
+							FALSE, lib->ns);
+
+	cfg = auth_cfg_create();
+	cfg->add_pubkey_constraints(cfg, sig_constraints_tests[_i].constraints, TRUE);
+	check_sig_constraints(cfg, AUTH_RULE_SIGNATURE_SCHEME, sig_constraints_tests[_i].sig);
+	check_sig_constraints(cfg, AUTH_RULE_IKE_SIGNATURE_SCHEME, sig_constraints_tests[_i].ike);
+	cfg->destroy(cfg);
+}
+END_TEST
+
+START_TEST(test_ike_contraints_fallback)
+{
+	auth_cfg_t *cfg;
+
+	lib->settings->set_bool(lib->settings, "%s.signature_authentication_constraints",
+							TRUE, lib->ns);
+
+	cfg = auth_cfg_create();
+	cfg->add_pubkey_constraints(cfg, sig_constraints_tests[_i].constraints, TRUE);
+	check_sig_constraints(cfg, AUTH_RULE_SIGNATURE_SCHEME, sig_constraints_tests[_i].sig);
+	if (sig_constraints_tests[_i].ike[0])
+	{
+		check_sig_constraints(cfg, AUTH_RULE_IKE_SIGNATURE_SCHEME, sig_constraints_tests[_i].ike);
+	}
+	else
+	{
+		check_sig_constraints(cfg, AUTH_RULE_IKE_SIGNATURE_SCHEME, sig_constraints_tests[_i].sig);
+	}
+	cfg->destroy(cfg);
+}
+END_TEST
+
+Suite *auth_cfg_suite_create()
+{
+	Suite *s;
+	TCase *tc;
+
+	s = suite_create("auth_cfg");
+
+	tc = tcase_create("add_pubkey_constraints");
+	tcase_add_loop_test(tc, test_sig_contraints, 0, countof(sig_constraints_tests));
+	tcase_add_loop_test(tc, test_ike_contraints_fallback, 0, countof(sig_constraints_tests));
+	suite_add_tcase(s, tc);
+
+	return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_identification.c b/src/libstrongswan/tests/suites/test_identification.c
index 9554d29..c0a21fe 100644
--- a/src/libstrongswan/tests/suites/test_identification.c
+++ b/src/libstrongswan/tests/suites/test_identification.c
@@ -1,7 +1,8 @@
 /*
  * Copyright (C) 2013-2015 Tobias Brunner
+ * Copyright (C) 2016 Andreas Steffen
  * Copyright (C) 2009 Martin Willi
- * Hochschule fuer Technik Rapperswil
+ * HSR 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
@@ -122,67 +123,122 @@ static struct {
 		} data;
 	} result;
 } string_data[] = {
-	{NULL,						ID_ANY,			{ .type = ENC_CHUNK }},
-	{"",						ID_ANY,			{ .type = ENC_CHUNK }},
-	{"%any",					ID_ANY,			{ .type = ENC_CHUNK }},
-	{"%any6",					ID_ANY,			{ .type = ENC_CHUNK }},
-	{"0.0.0.0",					ID_ANY,			{ .type = ENC_CHUNK }},
-	{"0::0",					ID_ANY,			{ .type = ENC_CHUNK }},
-	{"::",						ID_ANY,			{ .type = ENC_CHUNK }},
-	{"*",						ID_ANY,			{ .type = ENC_CHUNK }},
-	{"any",						ID_FQDN,		{ .type = ENC_SIMPLE }},
-	{"any6",					ID_FQDN,		{ .type = ENC_SIMPLE }},
-	{"0",						ID_FQDN,		{ .type = ENC_SIMPLE }},
-	{"**",						ID_FQDN,		{ .type = ENC_SIMPLE }},
-	{"192.168.1.1",				ID_IPV4_ADDR,	{ .type = ENC_CHUNK,
+	{NULL,						ID_ANY,					{ .type = ENC_CHUNK  }},
+	{"",						ID_ANY,					{ .type = ENC_CHUNK  }},
+	{"%any",					ID_ANY,					{ .type = ENC_CHUNK  }},
+	{"%any6",					ID_ANY,					{ .type = ENC_CHUNK  }},
+	{"0.0.0.0",					ID_ANY,					{ .type = ENC_CHUNK  }},
+	{"0::0",					ID_ANY,					{ .type = ENC_CHUNK  }},
+	{"::",						ID_ANY,					{ .type = ENC_CHUNK  }},
+	{"*",						ID_ANY,					{ .type = ENC_CHUNK  }},
+	{"any",						ID_FQDN,				{ .type = ENC_SIMPLE }},
+	{"any6",					ID_FQDN,				{ .type = ENC_SIMPLE }},
+	{"0",						ID_FQDN,				{ .type = ENC_SIMPLE }},
+	{"**",						ID_FQDN,				{ .type = ENC_SIMPLE }},
+	{"192.168.1.1",				ID_IPV4_ADDR,			{ .type = ENC_CHUNK,
 		.data.c = chunk_from_chars(0xc0,0xa8,0x01,0x01) }},
-	{"192.168.",				ID_FQDN,		{ .type = ENC_SIMPLE }},
-	{".",						ID_FQDN,		{ .type = ENC_SIMPLE }},
-	{"fec0::1",					ID_IPV6_ADDR,	{ .type = ENC_CHUNK,
+	{"192.168.",				ID_FQDN,				{ .type = ENC_SIMPLE }},
+	{".",						ID_FQDN,				{ .type = ENC_SIMPLE }},
+	{"192.168.1.1/33",			ID_FQDN,				{ .type = ENC_SIMPLE }},
+	{"192.168.1.1/32",			ID_IPV4_ADDR_SUBNET,	{ .type = ENC_CHUNK,
+		.data.c = chunk_from_chars(0xc0,0xa8,0x01,0x01,0xff,0xff,0xff,0xff)  }},
+	{"192.168.1.1/31",			ID_IPV4_ADDR_SUBNET,	{ .type = ENC_CHUNK,
+		.data.c = chunk_from_chars(0xc0,0xa8,0x01,0x00,0xff,0xff,0xff,0xfe)  }},
+	{"192.168.1.8/30",			ID_IPV4_ADDR_SUBNET,	{ .type = ENC_CHUNK,
+		.data.c = chunk_from_chars(0xc0,0xa8,0x01,0x08,0xff,0xff,0xff,0xfc)  }},
+	{"192.168.1.128/25",		ID_IPV4_ADDR_SUBNET,	{ .type = ENC_CHUNK,
+		.data.c = chunk_from_chars(0xc0,0xa8,0x01,0x80,0xff,0xff,0xff,0x80)  }},
+	{"192.168.1.0/24",			ID_IPV4_ADDR_SUBNET,	{ .type = ENC_CHUNK,
+		.data.c = chunk_from_chars(0xc0,0xa8,0x01,0x00,0xff,0xff,0xff,0x00)  }},
+	{"192.168.1.0/23",			ID_IPV4_ADDR_SUBNET,	{ .type = ENC_CHUNK,
+		.data.c = chunk_from_chars(0xc0,0xa8,0x00,0x00,0xff,0xff,0xfe,0x00)  }},
+	{"192.168.4.0/22",			ID_IPV4_ADDR_SUBNET,	{ .type = ENC_CHUNK,
+		.data.c = chunk_from_chars(0xc0,0xa8,0x04,0x00,0xff,0xff,0xfc,0x00)  }},
+	{"0.0.0.0/0",				ID_IPV4_ADDR_SUBNET,	{ .type = ENC_CHUNK,
+		.data.c = chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)  }},
+	{"192.168.1.0-192.168.1.40",ID_IPV4_ADDR_RANGE,		{ .type = ENC_CHUNK,
+		.data.c = chunk_from_chars(0xc0,0xa8,0x01,0x00,0xc0,0xa8,0x01,0x28)  }},
+	{"0.0.0.0-255.255.255.255",	ID_IPV4_ADDR_RANGE,		{ .type = ENC_CHUNK,
+		.data.c = chunk_from_chars(0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff)  }},
+	{"192.168.1.40-192.168.1.0",ID_FQDN,				{ .type = ENC_SIMPLE }},
+	{"fec0::1",					ID_IPV6_ADDR,			{ .type = ENC_CHUNK,
 		.data.c = chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
-								   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01) }},
-	{"fec0::",					ID_IPV6_ADDR,	{ .type = ENC_CHUNK,
+								   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01)  }},
+	{"fec0::",					ID_IPV6_ADDR,			{ .type = ENC_CHUNK,
 		.data.c = chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
-								   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00) }},
-	{"fec0:",					ID_KEY_ID,		{ .type = ENC_SIMPLE }},
-	{":",						ID_KEY_ID,		{ .type = ENC_SIMPLE }},
-	{"alice at strongswan.org",	ID_RFC822_ADDR,	{ .type = ENC_SIMPLE }},
-	{"alice at strongswan",		ID_RFC822_ADDR,	{ .type = ENC_SIMPLE }},
-	{"alice@",					ID_RFC822_ADDR,	{ .type = ENC_SIMPLE }},
-	{"alice",					ID_FQDN,		{ .type = ENC_SIMPLE }},
-	{"@",						ID_FQDN,		{ .type = ENC_CHUNK }},
-	{" @",						ID_RFC822_ADDR,	{ .type = ENC_SIMPLE }},
-	{"@strongswan.org",			ID_FQDN,		{ .type = ENC_STRING,
+								   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00)  }},
+	{"fec0:",					ID_KEY_ID,				{ .type = ENC_SIMPLE }},
+	{":",						ID_KEY_ID,				{ .type = ENC_SIMPLE }},
+	{"fec0::1/129",				ID_KEY_ID,				{ .type = ENC_SIMPLE }},
+	{"fec0::1/128",				ID_IPV6_ADDR_SUBNET,	{ .type = ENC_CHUNK,
+		.data.c = chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+								   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+								   0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+								   0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff ) }},
+	{"fec0::1/127",				ID_IPV6_ADDR_SUBNET,	{ .type = ENC_CHUNK,
+		.data.c = chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+								   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+								   0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+								   0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe ) }},
+	{"fec0::4/126",				ID_IPV6_ADDR_SUBNET,	{ .type = ENC_CHUNK,
+		.data.c = chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+								   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,
+								   0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+								   0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc ) }},
+	{"fec0::100/120",			ID_IPV6_ADDR_SUBNET,	{ .type = ENC_CHUNK,
+		.data.c = chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+								   0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
+								   0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+								   0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 ) }},
+	{"::/0",					ID_IPV6_ADDR_SUBNET,	{ .type = ENC_CHUNK,
+		.data.c = chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+								   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+								   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+								   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ) }},
+	{"fec0::1-fec0::4fff",		ID_IPV6_ADDR_RANGE,		{ .type = ENC_CHUNK,
+		.data.c = chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+								   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+								   0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+								   0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0xff ) }},
+	{"fec0::4fff-fec0::1",		ID_KEY_ID,				{ .type = ENC_SIMPLE }},
+	{"fec0::1-",				ID_KEY_ID,				{ .type = ENC_SIMPLE }},
+	{"alice at strongswan.org",	ID_RFC822_ADDR,			{ .type = ENC_SIMPLE }},
+	{"alice at strongswan",		ID_RFC822_ADDR,			{ .type = ENC_SIMPLE }},
+	{"alice@",					ID_RFC822_ADDR,			{ .type = ENC_SIMPLE }},
+	{"alice",					ID_FQDN,				{ .type = ENC_SIMPLE }},
+	{"@",						ID_FQDN,				{ .type = ENC_CHUNK }},
+	{" @",						ID_RFC822_ADDR,			{ .type = ENC_SIMPLE }},
+	{"@strongswan.org",			ID_FQDN,				{ .type = ENC_STRING,
 		.data.s = "strongswan.org" }},
-	{"@#deadbeef",				ID_KEY_ID,		{ .type = ENC_CHUNK,
+	{"@#deadbeef",				ID_KEY_ID,				{ .type = ENC_CHUNK,
 		.data.c = chunk_from_chars(0xde,0xad,0xbe,0xef) }},
-	{"@#deadbee",				ID_KEY_ID,		{ .type = ENC_CHUNK,
+	{"@#deadbee",				ID_KEY_ID,				{ .type = ENC_CHUNK,
 		.data.c = chunk_from_chars(0x0d,0xea,0xdb,0xee) }},
-	{"foo=bar",					ID_KEY_ID,		{ .type = ENC_SIMPLE }},
-	{"foo=",					ID_KEY_ID,		{ .type = ENC_SIMPLE }},
-	{"=bar",					ID_KEY_ID,		{ .type = ENC_SIMPLE }},
-	{"C=",						ID_DER_ASN1_DN,	{ .type = ENC_CHUNK,
+	{"foo=bar",					ID_KEY_ID,				{ .type = ENC_SIMPLE }},
+	{"foo=",					ID_KEY_ID,				{ .type = ENC_SIMPLE }},
+	{"=bar",					ID_KEY_ID,				{ .type = ENC_SIMPLE }},
+	{"C=",						ID_DER_ASN1_DN,			{ .type = ENC_CHUNK,
 		.data.c = chunk_from_chars(0x30,0x0b,0x31,0x09,0x30,0x07,0x06,
 								   0x03,0x55,0x04,0x06,0x13,0x00) }},
-	{"C=CH",					ID_DER_ASN1_DN,	{ .type = ENC_CHUNK,
+	{"C=CH",					ID_DER_ASN1_DN,			{ .type = ENC_CHUNK,
 		.data.c = chunk_from_chars(0x30,0x0d,0x31,0x0b,0x30,0x09,0x06,
 								   0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48) }},
-	{"C=CH,",					ID_DER_ASN1_DN,	{ .type = ENC_CHUNK,
+	{"C=CH,",					ID_DER_ASN1_DN,			{ .type = ENC_CHUNK,
 		.data.c = chunk_from_chars(0x30,0x0d,0x31,0x0b,0x30,0x09,0x06,
 								   0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48) }},
-	{"C=CH, ",					ID_DER_ASN1_DN,	{ .type = ENC_CHUNK,
+	{"C=CH, ",					ID_DER_ASN1_DN,			{ .type = ENC_CHUNK,
 		.data.c = chunk_from_chars(0x30,0x0d,0x31,0x0b,0x30,0x09,0x06,
 								   0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48) }},
-	{"C=CH, O",					ID_KEY_ID,		{ .type = ENC_SIMPLE }},
-	{"IPv4:#c0a80101",			ID_IPV4_ADDR,	{ .type = ENC_CHUNK,
+	{"C=CH, O",					ID_KEY_ID,				{ .type = ENC_SIMPLE }},
+	{"IPv4:#c0a80101",			ID_IPV4_ADDR,			{ .type = ENC_CHUNK,
 		.data.c = chunk_from_chars(0xc0,0xa8,0x01,0x01) }},
-	{ "email:tester",			ID_RFC822_ADDR,	{ .type = ENC_STRING,
+	{ "email:tester",			ID_RFC822_ADDR,			{ .type = ENC_STRING,
 		.data.s = "tester" }},
-	{ "{1}:#c0a80101",			ID_IPV4_ADDR,	{ .type = ENC_CHUNK,
+	{ "{1}:#c0a80101",			ID_IPV4_ADDR,			{ .type = ENC_CHUNK,
 		.data.c = chunk_from_chars(0xc0,0xa8,0x01,0x01) }},
-	{ "{0x02}:tester",			ID_FQDN,		{ .type = ENC_STRING,
+	{ "{0x02}:tester",			ID_FQDN,				{ .type = ENC_STRING,
 		.data.s = "tester" }},
-	{ "{99}:somedata",			99,				{ .type = ENC_STRING,
+	{ "{99}:somedata",			99,						{ .type = ENC_STRING,
 		.data.s = "somedata" }},
 };
 
@@ -264,14 +320,33 @@ START_TEST(test_printf_hook)
 
 	string_equals("192.168.1.1", "192.168.1.1");
 	string_equals_id("(invalid ID_IPV4_ADDR)",
-				identification_create_from_encoding(ID_IPV4_ADDR, chunk_empty));
+			identification_create_from_encoding(ID_IPV4_ADDR, chunk_empty));
+	string_equals("192.168.1.1/32", "192.168.1.1/32");
+	string_equals("192.168.1.2/31", "192.168.1.2/31");
+	string_equals("192.168.1.0/24", "192.168.1.0/24");
+	string_equals("192.168.2.0/23", "192.168.2.0/23");
+	string_equals("0.0.0.0/0", "0.0.0.0/0");
+	string_equals_id("(invalid ID_IPV4_ADDR_SUBNET)",
+			identification_create_from_encoding(ID_IPV4_ADDR_SUBNET, chunk_empty));
+	string_equals("192.168.1.1-192.168.1.254", "192.168.1.1-192.168.1.254");
+	string_equals("0.0.0.0-255.255.255.255", "0.0.0.0-255.255.255.255");
+	string_equals_id("(invalid ID_IPV4_ADDR_RANGE)",
+			identification_create_from_encoding(ID_IPV4_ADDR_RANGE, chunk_empty));
 	string_equals("fec0::1", "fec0::1");
 	string_equals("fec0::1", "fec0:0:0::1");
 	string_equals_id("(invalid ID_IPV6_ADDR)",
-				identification_create_from_encoding(ID_IPV6_ADDR, chunk_empty));
-
+			identification_create_from_encoding(ID_IPV6_ADDR, chunk_empty));
+	string_equals("fec0::1/128", "fec0::1/128");
+	string_equals("fec0::2/127", "fec0::2/127");
+	string_equals("fec0::100/120", "fec0::100/120");
+	string_equals("::/0", "::/0");
+	string_equals_id("(invalid ID_IPV6_ADDR_SUBNET)",
+			identification_create_from_encoding(ID_IPV6_ADDR_SUBNET, chunk_empty));
+	string_equals("fec0::1-fec0::4fff", "fec0::1-fec0::4fff");
+	string_equals_id("(invalid ID_IPV6_ADDR_RANGE)",
+			identification_create_from_encoding(ID_IPV6_ADDR_RANGE, chunk_empty));
 	string_equals_id("(unknown ID type: 255)",
-				identification_create_from_encoding(255, chunk_empty));
+			identification_create_from_encoding(255, chunk_empty));
 
 	string_equals("moon at strongswan.org", "moon at strongswan.org");
 	string_equals("MOON at STRONGSWAN.ORG", "MOON at STRONGSWAN.ORG");
@@ -324,11 +399,11 @@ START_TEST(test_printf_hook)
 	string_equals("C=CH, E=moon at strongswan.org, CN=moon",
 				  "C=CH, emailAddress=moon at strongswan.org, CN=moon");
 
-	/* C=CH, pseudonym=ANO (pseudonym is currently not recognized) */
-	string_equals_id("C=CH, 55:04:41=ANO", identification_create_from_encoding(ID_DER_ASN1_DN,
+	/* C=CH, telexNumber=123 (telexNumber is currently not recognized) */
+	string_equals_id("C=CH, 55:04:15=123", identification_create_from_encoding(ID_DER_ASN1_DN,
 		chunk_from_chars(0x30, 0x19, 0x31, 0x17, 0x30, 0x09, 0x06, 0x03, 0x55,
 						 0x04, 0x06, 0x13, 0x02, 0x43, 0x48, 0x30, 0x0a, 0x06,
-						 0x03, 0x55, 0x04, 0x41, 0x13, 0x03, 0x41, 0x4e, 0x4f)));
+						 0x03, 0x55, 0x04, 0x15, 0x13, 0x03, 0x31, 0x32, 0x33)));
 	/* C=CH, O=strongSwan (but instead of a 2nd OID -0x06- we got NULL -0x05) */
 	string_equals_id("C=CH, (invalid ID_DER_ASN1_DN)", identification_create_from_encoding(ID_DER_ASN1_DN,
 		chunk_from_chars(0x30, 0x20, 0x31, 0x1e, 0x30, 0x09, 0x06, 0x03, 0x55,
@@ -595,6 +670,89 @@ START_TEST(test_matches_binary)
 }
 END_TEST
 
+START_TEST(test_matches_range)
+{
+	identification_t *a, *b;
+
+	/* IPv4 addresses */
+	a = identification_create_from_string("192.168.1.1");
+	ck_assert(a->get_type(a) == ID_IPV4_ADDR);
+	ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
+	ck_assert(id_matches(a, "0.0.0.0/0", ID_MATCH_MAX_WILDCARDS));
+	ck_assert(id_matches(a, "192.168.1.1", ID_MATCH_PERFECT));
+	ck_assert(id_matches(a, "192.168.1.2", ID_MATCH_NONE));
+	ck_assert(id_matches(a, "192.168.1.1/32", ID_MATCH_PERFECT));
+	ck_assert(id_matches(a, "192.168.1.0/32", ID_MATCH_NONE));
+	ck_assert(id_matches(a, "192.168.1.0/24", ID_MATCH_ONE_WILDCARD));
+	ck_assert(id_matches(a, "192.168.0.0/24", ID_MATCH_NONE));
+	ck_assert(id_matches(a, "192.168.1.1-192.168.1.1", ID_MATCH_PERFECT));
+	ck_assert(id_matches(a, "192.168.1.0-192.168.1.64", ID_MATCH_ONE_WILDCARD));
+	ck_assert(id_matches(a, "192.168.1.2-192.168.1.64", ID_MATCH_NONE));
+	ck_assert(id_matches(a, "192.168.0.240-192.168.1.0", ID_MATCH_NONE));
+	ck_assert(id_matches(a, "foo at bar", ID_MATCH_NONE));
+
+	/* Malformed IPv4 subnet and range encoding */
+	b = identification_create_from_encoding(ID_IPV4_ADDR_SUBNET, chunk_empty);
+	ck_assert(a->matches(a, b) == ID_MATCH_NONE);
+	b->destroy(b);
+	b = identification_create_from_encoding(ID_IPV4_ADDR_RANGE, chunk_empty);
+	ck_assert(a->matches(a, b) == ID_MATCH_NONE);
+	b->destroy(b);
+	b = identification_create_from_encoding(ID_IPV4_ADDR_RANGE,
+			chunk_from_chars(0xc0,0xa8,0x01,0x28,0xc0,0xa8,0x01,0x00));
+	ck_assert(a->matches(a, b) == ID_MATCH_NONE);
+	b->destroy(b);
+
+	a->destroy(a);
+
+	/* IPv6 addresses */
+	a = identification_create_from_string("fec0::1");
+	ck_assert(a->get_type(a) == ID_IPV6_ADDR);
+	ck_assert(id_matches(a, "%any", ID_MATCH_ANY));
+	ck_assert(id_matches(a, "::/0", ID_MATCH_MAX_WILDCARDS));
+	ck_assert(id_matches(a, "fec0::1", ID_MATCH_PERFECT));
+	ck_assert(id_matches(a, "fec0::2", ID_MATCH_NONE));
+	ck_assert(id_matches(a, "fec0::1/128", ID_MATCH_PERFECT));
+	ck_assert(id_matches(a, "fec0::/128", ID_MATCH_NONE));
+	ck_assert(id_matches(a, "fec0::/120", ID_MATCH_ONE_WILDCARD));
+	ck_assert(id_matches(a, "fec0::100/120", ID_MATCH_NONE));
+	ck_assert(id_matches(a, "fec0::1-fec0::1", ID_MATCH_PERFECT));
+	ck_assert(id_matches(a, "fec0::0-fec0::5", ID_MATCH_ONE_WILDCARD));
+	ck_assert(id_matches(a, "fec0::4001-fec0::4ffe", ID_MATCH_NONE));
+	ck_assert(id_matches(a, "feb0::1-fec0::0", ID_MATCH_NONE));
+	ck_assert(id_matches(a, "foo at bar", ID_MATCH_NONE));
+
+	/* Malformed IPv6 subnet and range encoding */
+	b = identification_create_from_encoding(ID_IPV6_ADDR_SUBNET, chunk_empty);
+	ck_assert(a->matches(a, b) == ID_MATCH_NONE);
+	b->destroy(b);
+	b = identification_create_from_encoding(ID_IPV6_ADDR_RANGE, chunk_empty);
+	ck_assert(a->matches(a, b) == ID_MATCH_NONE);
+	b->destroy(b);
+	b = identification_create_from_encoding(ID_IPV6_ADDR_RANGE,
+			chunk_from_chars(0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+							 0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0xff,
+							 0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+							 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 ));
+	ck_assert(a->matches(a, b) == ID_MATCH_NONE);
+	b->destroy(b);
+
+	a->destroy(a);
+
+	/* Malformed IPv4 address encoding */
+	a = identification_create_from_encoding(ID_IPV4_ADDR, chunk_empty);
+	ck_assert(id_matches(a, "0.0.0.0/0", ID_MATCH_NONE));
+	ck_assert(id_matches(a, "0.0.0.0-255.255.255.255", ID_MATCH_NONE));
+	a->destroy(a);
+
+	/* Malformed IPv6 address encoding */
+	a = identification_create_from_encoding(ID_IPV6_ADDR, chunk_empty);
+	ck_assert(id_matches(a, "::/0", ID_MATCH_NONE));
+	ck_assert(id_matches(a, "::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", ID_MATCH_NONE));
+	a->destroy(a);
+}
+END_TEST
+
 START_TEST(test_matches_string)
 {
 	identification_t *a;
@@ -929,6 +1087,7 @@ Suite *identification_suite_create()
 	tcase_add_test(tc, test_matches);
 	tcase_add_test(tc, test_matches_any);
 	tcase_add_test(tc, test_matches_binary);
+	tcase_add_test(tc, test_matches_range);
 	tcase_add_test(tc, test_matches_string);
 	tcase_add_loop_test(tc, test_matches_empty, ID_ANY, ID_KEY_ID + 1);
 	tcase_add_loop_test(tc, test_matches_empty_reverse, ID_ANY, ID_KEY_ID + 1);
diff --git a/src/libstrongswan/tests/suites/test_linked_list.c b/src/libstrongswan/tests/suites/test_linked_list.c
index 922f954..7a16181 100644
--- a/src/libstrongswan/tests/suites/test_linked_list.c
+++ b/src/libstrongswan/tests/suites/test_linked_list.c
@@ -348,6 +348,91 @@ START_TEST(test_clone_offset)
 }
 END_TEST
 
+
+/*******************************************************************************
+ * equals
+ */
+
+typedef struct equals_t equals_t;
+
+struct equals_t {
+	int val;
+	bool (*equals)(equals_t *a, equals_t *b);
+};
+
+static bool equalsfn(equals_t *a, equals_t *b)
+{
+	return a->val == b->val;
+}
+
+START_TEST(test_equals_offset)
+{
+	linked_list_t *other;
+	equals_t *x, items[] = {
+		{ .val = 1, .equals = equalsfn, },
+		{ .val = 2, .equals = equalsfn, },
+		{ .val = 3, .equals = equalsfn, },
+		{ .val = 4, .equals = equalsfn, },
+		{ .val = 5, .equals = equalsfn, },
+	};
+	int i;
+
+	for (i = 0; i < countof(items); i++)
+	{
+		list->insert_last(list, &items[i]);
+	}
+	ck_assert(list->equals_offset(list, list, offsetof(equals_t, equals)));
+	other = linked_list_create_from_enumerator(list->create_enumerator(list));
+	ck_assert(list->equals_offset(list, other, offsetof(equals_t, equals)));
+	other->remove_last(other, (void**)&x);
+	ck_assert(!list->equals_offset(list, other, offsetof(equals_t, equals)));
+	list->remove_last(list, (void**)&x);
+	ck_assert(list->equals_offset(list, other, offsetof(equals_t, equals)));
+	other->remove_first(other, (void**)&x);
+	ck_assert(!list->equals_offset(list, other, offsetof(equals_t, equals)));
+	list->remove_first(list, (void**)&x);
+	ck_assert(list->equals_offset(list, other, offsetof(equals_t, equals)));
+	while (list->remove_first(list, (void**)&x) == SUCCESS);
+	while (other->remove_first(other, (void**)&x) == SUCCESS);
+	ck_assert(list->equals_offset(list, other, offsetof(equals_t, equals)));
+	other->destroy(other);
+}
+END_TEST
+
+START_TEST(test_equals_function)
+{
+	linked_list_t *other;
+	equals_t *x, items[] = {
+		{ .val = 1, },
+		{ .val = 2, },
+		{ .val = 3, },
+		{ .val = 4, },
+		{ .val = 5, },
+	};
+	int i;
+
+	for (i = 0; i < countof(items); i++)
+	{
+		list->insert_last(list, &items[i]);
+	}
+	ck_assert(list->equals_function(list, list, (void*)equalsfn));
+	other = linked_list_create_from_enumerator(list->create_enumerator(list));
+	ck_assert(list->equals_function(list, other, (void*)equalsfn));
+	other->remove_last(other, (void**)&x);
+	ck_assert(!list->equals_function(list, other, (void*)equalsfn));
+	list->remove_last(list, (void**)&x);
+	ck_assert(list->equals_function(list, other, (void*)equalsfn));
+	other->remove_first(other, (void**)&x);
+	ck_assert(!list->equals_function(list, other, (void*)equalsfn));
+	list->remove_first(list, (void**)&x);
+	ck_assert(list->equals_function(list, other, (void*)equalsfn));
+	while (list->remove_first(list, (void**)&x) == SUCCESS);
+	while (other->remove_first(other, (void**)&x) == SUCCESS);
+	ck_assert(list->equals_function(list, other, (void*)equalsfn));
+	other->destroy(other);
+}
+END_TEST
+
 Suite *linked_list_suite_create()
 {
 	Suite *s;
@@ -386,5 +471,11 @@ Suite *linked_list_suite_create()
 	tcase_add_test(tc, test_clone_offset);
 	suite_add_tcase(s, tc);
 
+	tc = tcase_create("equals");
+	tcase_add_checked_fixture(tc, setup_list, teardown_list);
+	tcase_add_test(tc, test_equals_offset);
+	tcase_add_test(tc, test_equals_function);
+	suite_add_tcase(s, tc);
+
 	return s;
 }
diff --git a/src/libstrongswan/tests/tests.h b/src/libstrongswan/tests/tests.h
index e1074b9..824c880 100644
--- a/src/libstrongswan/tests/tests.h
+++ b/src/libstrongswan/tests/tests.h
@@ -37,6 +37,7 @@ TEST_SUITE_DEPEND(certpolicy_suite_create, CERT_ENCODE, CERT_X509)
 TEST_SUITE_DEPEND(certnames_suite_create, CERT_ENCODE, CERT_X509)
 TEST_SUITE(host_suite_create)
 TEST_SUITE(printf_suite_create)
+TEST_SUITE(auth_cfg_suite_create)
 TEST_SUITE(hasher_suite_create)
 TEST_SUITE(crypter_suite_create)
 TEST_SUITE(crypto_factory_suite_create)
diff --git a/src/libstrongswan/threading/thread.c b/src/libstrongswan/threading/thread.c
index 7a243e8..3d87e7f 100644
--- a/src/libstrongswan/threading/thread.c
+++ b/src/libstrongswan/threading/thread.c
@@ -48,7 +48,7 @@ struct private_thread_t {
 	thread_t public;
 
 	/**
-	 * Human-readable ID of this thread.
+	 * Identificator of this thread (human-readable/thread ID).
 	 */
 	u_int id;
 
@@ -157,6 +157,23 @@ static void thread_destroy(private_thread_t *this)
 	free(this);
 }
 
+/**
+ * Determine the ID of the current thread
+ */
+static u_int get_thread_id()
+{
+	u_int id;
+
+#if defined(USE_THREAD_IDS) && defined(HAVE_GETTID)
+	id = gettid();
+#else
+	id_mutex->lock(id_mutex);
+	id = next_id++;
+	id_mutex->unlock(id_mutex);
+#endif
+	return id;
+}
+
 METHOD(thread_t, cancel, void,
 	private_thread_t *this)
 {
@@ -284,6 +301,8 @@ static void *thread_main(private_thread_t *this)
 {
 	void *res;
 
+	this->id = get_thread_id();
+
 	current_thread->set(current_thread, this);
 	pthread_cleanup_push((thread_cleanup_t)thread_cleanup, this);
 
@@ -315,9 +334,6 @@ thread_t *thread_create(thread_main_t main, void *arg)
 
 	this->main = main;
 	this->arg = arg;
-	id_mutex->lock(id_mutex);
-	this->id = next_id++;
-	id_mutex->unlock(id_mutex);
 
 	if (pthread_create(&this->thread_id, NULL, (void*)thread_main, this) != 0)
 	{
@@ -341,11 +357,7 @@ thread_t *thread_current()
 	if (!this)
 	{
 		this = thread_create_internal();
-
-		id_mutex->lock(id_mutex);
-		this->id = next_id++;
-		id_mutex->unlock(id_mutex);
-
+		this->id = get_thread_id();
 		current_thread->set(current_thread, (void*)this);
 	}
 	return &this->public;
@@ -475,12 +487,12 @@ void threads_init()
 
 	dummy1 = thread_value_create(NULL);
 
-	next_id = 1;
-	main_thread->id = 0;
+	next_id = 0;
 	main_thread->thread_id = pthread_self();
 	current_thread = thread_value_create(NULL);
 	current_thread->set(current_thread, (void*)main_thread);
 	id_mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+	main_thread->id = get_thread_id();
 
 #ifndef HAVE_PTHREAD_CANCEL
 	{	/* install a signal handler for our custom SIG_CANCEL */
diff --git a/src/libstrongswan/threading/thread.h b/src/libstrongswan/threading/thread.h
index c247728..35da244 100644
--- a/src/libstrongswan/threading/thread.h
+++ b/src/libstrongswan/threading/thread.h
@@ -97,11 +97,13 @@ thread_t *thread_create(thread_main_t main, void *arg);
 thread_t *thread_current();
 
 /**
- * Get the human-readable ID of the current thread.
+ * Get the ID of the current thread.
  *
- * The IDs are assigned incrementally starting from 1.
+ * Depending on the build configuration thread IDs are either assigned
+ * incrementally starting from 1, or equal the value returned by an appropriate
+ * syscall (like gettid() or GetCurrentThreadId()), if available.
  *
- * @return				human-readable ID
+ * @return				ID of the current thread
  */
 u_int thread_current_id();
 
diff --git a/src/libstrongswan/threading/windows/thread.c b/src/libstrongswan/threading/windows/thread.c
index 6105247..798d75b 100644
--- a/src/libstrongswan/threading/windows/thread.c
+++ b/src/libstrongswan/threading/windows/thread.c
@@ -516,7 +516,11 @@ thread_t *thread_current()
  */
 u_int thread_current_id()
 {
+#ifdef USE_THREAD_IDS
+	return get_current_thread()->id;
+#else
 	return get_current_thread()->tid;
+#endif
 }
 
 /**
diff --git a/src/libstrongswan/utils/compat/windows.c b/src/libstrongswan/utils/compat/windows.c
index 1f22ffa..12ee599 100644
--- a/src/libstrongswan/utils/compat/windows.c
+++ b/src/libstrongswan/utils/compat/windows.c
@@ -82,7 +82,6 @@ static void* dlsym_default(const char *name)
 {
 	const char *dlls[] = {
 		"libstrongswan-0.dll",
-		"libhydra-0.dll",
 		"libcharon-0.dll",
 		"libtnccs-0.dll",
 		NULL /* .exe */
diff --git a/src/libstrongswan/utils/debug.c b/src/libstrongswan/utils/debug.c
index e8c9e6b..8a80b81 100644
--- a/src/libstrongswan/utils/debug.c
+++ b/src/libstrongswan/utils/debug.c
@@ -17,7 +17,7 @@
 
 #include "debug.h"
 
-ENUM(debug_names, DBG_DMN, DBG_LIB,
+ENUM(debug_names, DBG_DMN, DBG_ANY,
 	"DMN",
 	"MGR",
 	"IKE",
@@ -36,9 +36,10 @@ ENUM(debug_names, DBG_DMN, DBG_LIB,
 	"APP",
 	"ESP",
 	"LIB",
+	"ANY",
 );
 
-ENUM(debug_lower_names, DBG_DMN, DBG_LIB,
+ENUM(debug_lower_names, DBG_DMN, DBG_ANY,
 	"dmn",
 	"mgr",
 	"ike",
@@ -57,6 +58,7 @@ ENUM(debug_lower_names, DBG_DMN, DBG_LIB,
 	"app",
 	"esp",
 	"lib",
+	"any",
 );
 
 /**
diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c
index da23d14..2b2e907 100644
--- a/src/libstrongswan/utils/identification.c
+++ b/src/libstrongswan/utils/identification.c
@@ -1,8 +1,9 @@
 /*
+ * Copyright (C) 2016 Andreas Steffen
  * Copyright (C) 2009-2015 Tobias Brunner
  * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
+ * HSR 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
@@ -79,6 +80,7 @@ static const x501rdn_t x501rdns[] = {
 	{"G", 					OID_GIVEN_NAME,				ASN1_PRINTABLESTRING},
 	{"I", 					OID_INITIALS,				ASN1_PRINTABLESTRING},
 	{"dnQualifier", 		OID_DN_QUALIFIER,			ASN1_PRINTABLESTRING},
+	{"pseudonym", 			OID_PSEUDONYM,				ASN1_PRINTABLESTRING},
 	{"ID", 					OID_UNIQUE_IDENTIFIER,		ASN1_PRINTABLESTRING},
 	{"EN", 					OID_EMPLOYEE_NUMBER,		ASN1_PRINTABLESTRING},
 	{"employeeNumber",		OID_EMPLOYEE_NUMBER,		ASN1_PRINTABLESTRING},
@@ -218,6 +220,7 @@ METHOD(enumerator_t, rdn_part_enumerate, bool,
 		{OID_GIVEN_NAME,		ID_PART_RDN_G},
 		{OID_INITIALS,			ID_PART_RDN_I},
 		{OID_DN_QUALIFIER,		ID_PART_RDN_DNQ},
+		{OID_PSEUDONYM,			ID_PART_RDN_PN},
 		{OID_UNIQUE_IDENTIFIER,	ID_PART_RDN_ID},
 		{OID_EMAIL_ADDRESS,		ID_PART_RDN_E},
 		{OID_EMPLOYEE_NUMBER,	ID_PART_RDN_EN},
@@ -822,6 +825,154 @@ METHOD(identification_t, matches_dn, id_match_t,
 }
 
 /**
+ * Transform netmask to CIDR bits
+ */
+static int netmask_to_cidr(char *netmask, size_t address_size)
+{
+	uint8_t byte;
+	int i, netbits = 0;
+
+	for (i = 0; i < address_size; i++)
+	{
+		byte = netmask[i];
+
+		if (byte == 0x00)
+		{
+			break;
+		}
+		if (byte == 0xff)
+		{
+			netbits += 8;
+		}
+		else
+		{
+			while (byte & 0x80)
+			{
+				netbits++;
+				byte <<= 1;
+			}
+		}
+	}
+	return netbits;
+}
+
+METHOD(identification_t, matches_range, id_match_t,
+	private_identification_t *this, identification_t *other)
+{
+	chunk_t other_encoding;
+	uint8_t *address, *from, *to, *network, *netmask;
+	size_t address_size = 0;
+	int netbits, range_sign, i;
+
+	if (other->get_type(other) == ID_ANY)
+	{
+		return ID_MATCH_ANY;
+	}
+	if (this->type == other->get_type(other) &&
+		chunk_equals(this->encoded, other->get_encoding(other)))
+	{
+		return ID_MATCH_PERFECT;
+	}
+	if ((this->type == ID_IPV4_ADDR &&
+		 other->get_type(other) == ID_IPV4_ADDR_SUBNET))
+	{
+		address_size = sizeof(struct in_addr);
+	}
+	else if ((this->type == ID_IPV6_ADDR &&
+		 other->get_type(other) == ID_IPV6_ADDR_SUBNET))
+	{
+		address_size = sizeof(struct in6_addr);
+	}
+	if (address_size)
+	{
+		other_encoding = other->get_encoding(other);
+		if (this->encoded.len != address_size ||
+			other_encoding.len != 2 * address_size)
+		{
+			return ID_MATCH_NONE;
+		}
+		address = this->encoded.ptr;
+		network = other_encoding.ptr;
+		netmask = other_encoding.ptr + address_size;
+		netbits = netmask_to_cidr(netmask, address_size);
+
+		if (netbits == 0)
+		{
+			return ID_MATCH_MAX_WILDCARDS;
+		}
+		if (netbits == 8 * address_size)
+		{
+			return memeq(address, network, address_size) ?
+				   ID_MATCH_PERFECT : ID_MATCH_NONE;
+		}
+		for (i = 0; i < (netbits + 7)/8; i++)
+		{
+			if ((address[i] ^ network[i]) & netmask[i])
+			{
+				return ID_MATCH_NONE;
+			}
+		}
+		return ID_MATCH_ONE_WILDCARD;
+	}
+	if ((this->type == ID_IPV4_ADDR &&
+		 other->get_type(other) == ID_IPV4_ADDR_RANGE))
+	{
+		address_size = sizeof(struct in_addr);
+	}
+	else if ((this->type == ID_IPV6_ADDR &&
+		 other->get_type(other) == ID_IPV6_ADDR_RANGE))
+	{
+		address_size = sizeof(struct in6_addr);
+	}
+	if (address_size)
+	{
+		other_encoding = other->get_encoding(other);
+		if (this->encoded.len != address_size ||
+			other_encoding.len != 2 * address_size)
+		{
+			return ID_MATCH_NONE;
+		}
+		address = this->encoded.ptr;
+		from = other_encoding.ptr;
+		to = other_encoding.ptr + address_size;
+
+		range_sign = memcmp(to, from, address_size);
+		if (range_sign < 0)
+		{	/* to is smaller than from */
+			return ID_MATCH_NONE;
+		}
+
+		/* check lower bound */
+		for (i = 0; i < address_size; i++)
+		{
+			if (address[i] != from[i])
+			{
+				if (address[i] < from[i])
+				{
+					return ID_MATCH_NONE;
+				}
+				break;
+			}
+		}
+
+		/* check upper bound */
+		for (i = 0; i < address_size; i++)
+		{
+			if (address[i] != to[i])
+			{
+				if (address[i] > to[i])
+				{
+					return ID_MATCH_NONE;
+				}
+				break;
+			}
+		}
+		return range_sign ? ID_MATCH_ONE_WILDCARD : ID_MATCH_PERFECT;
+	}
+	return ID_MATCH_NONE;
+}
+
+/**
  * Described in header.
  */
 int identification_printf_hook(printf_hook_data_t *data,
@@ -829,7 +980,9 @@ int identification_printf_hook(printf_hook_data_t *data,
 {
 	private_identification_t *this = *((private_identification_t**)(args[0]));
 	chunk_t proper;
-	char buf[512];
+	char buf[BUF_LEN], *pos;
+	size_t len, address_size;
+	int written;
 
 	if (this == NULL)
 	{
@@ -839,49 +992,115 @@ int identification_printf_hook(printf_hook_data_t *data,
 	switch (this->type)
 	{
 		case ID_ANY:
-			snprintf(buf, sizeof(buf), "%%any");
+			snprintf(buf, BUF_LEN, "%%any");
 			break;
 		case ID_IPV4_ADDR:
 			if (this->encoded.len < sizeof(struct in_addr) ||
-				inet_ntop(AF_INET, this->encoded.ptr, buf, sizeof(buf)) == NULL)
+				inet_ntop(AF_INET, this->encoded.ptr, buf, BUF_LEN) == NULL)
 			{
-				snprintf(buf, sizeof(buf), "(invalid ID_IPV4_ADDR)");
+				snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR)");
+			}
+			break;
+		case ID_IPV4_ADDR_SUBNET:
+			address_size = sizeof(struct in_addr);
+			if (this->encoded.len < 2 * address_size ||
+				inet_ntop(AF_INET, this->encoded.ptr, buf, BUF_LEN) == NULL)
+			{
+				snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR_SUBNET)");
+				break;
+			}
+			written = strlen(buf);
+			snprintf(buf + written, BUF_LEN - written, "/%d",
+					 netmask_to_cidr(this->encoded.ptr + address_size,
+														 address_size));
+			break;
+		case ID_IPV4_ADDR_RANGE:
+			address_size = sizeof(struct in_addr);
+			if (this->encoded.len < 2 * address_size ||
+				inet_ntop(AF_INET, this->encoded.ptr, buf, BUF_LEN) == NULL)
+			{
+				snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR_RANGE)");
+				break;
+			}
+			written = strlen(buf);
+			pos = buf + written;
+			len = BUF_LEN - written;
+			written = snprintf(pos, len, "-");
+			if (written < 0 || written >= len ||
+			    inet_ntop(AF_INET, this->encoded.ptr + address_size,
+						  pos + written, len - written) == NULL)
+			{
+				snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR_RANGE)");
 			}
 			break;
 		case ID_IPV6_ADDR:
 			if (this->encoded.len < sizeof(struct in6_addr) ||
-				inet_ntop(AF_INET6, this->encoded.ptr, buf, INET6_ADDRSTRLEN) == NULL)
+				inet_ntop(AF_INET6, this->encoded.ptr, buf, BUF_LEN) == NULL)
+			{
+				snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR)");
+			}
+			break;
+		case ID_IPV6_ADDR_SUBNET:
+			address_size = sizeof(struct in6_addr);
+			if (this->encoded.len < 2 * address_size ||
+				inet_ntop(AF_INET6, this->encoded.ptr, buf, BUF_LEN) == NULL)
+			{
+				snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR_SUBNET)");
+			}
+			else
 			{
-				snprintf(buf, sizeof(buf), "(invalid ID_IPV6_ADDR)");
+				written = strlen(buf);
+				snprintf(buf + written, BUF_LEN - written, "/%d",
+						 netmask_to_cidr(this->encoded.ptr + address_size,
+															 address_size));
+			}
+			break;
+		case ID_IPV6_ADDR_RANGE:
+			address_size = sizeof(struct in6_addr);
+			if (this->encoded.len < 2 * address_size ||
+				inet_ntop(AF_INET6, this->encoded.ptr, buf, BUF_LEN) == NULL)
+			{
+				snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR_RANGE)");
+				break;
+			}
+			written = strlen(buf);
+			pos = buf + written;
+			len = BUF_LEN - written;
+			written = snprintf(pos, len, "-");
+			if (written < 0 || written >= len ||
+			    inet_ntop(AF_INET6, this->encoded.ptr + address_size,
+						  pos + written, len - written) == NULL)
+			{
+				snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR_RANGE)");
 			}
 			break;
 		case ID_FQDN:
 		case ID_RFC822_ADDR:
 		case ID_DER_ASN1_GN_URI:
 			chunk_printable(this->encoded, &proper, '?');
-			snprintf(buf, sizeof(buf), "%.*s", (int)proper.len, proper.ptr);
+			snprintf(buf, BUF_LEN, "%.*s", (int)proper.len, proper.ptr);
 			chunk_free(&proper);
 			break;
 		case ID_DER_ASN1_DN:
-			dntoa(this->encoded, buf, sizeof(buf));
+			dntoa(this->encoded, buf, BUF_LEN);
 			break;
 		case ID_DER_ASN1_GN:
-			snprintf(buf, sizeof(buf), "(ASN.1 general name)");
+			snprintf(buf, BUF_LEN, "(ASN.1 general name)");
 			break;
 		case ID_KEY_ID:
 			if (chunk_printable(this->encoded, NULL, '?') &&
 				this->encoded.len != HASH_SIZE_SHA1)
 			{	/* fully printable, use ascii version */
-				snprintf(buf, sizeof(buf), "%.*s", (int)this->encoded.len,
+				snprintf(buf, BUF_LEN, "%.*s", (int)this->encoded.len,
 						 this->encoded.ptr);
 			}
 			else
 			{	/* not printable, hex dump */
-				snprintf(buf, sizeof(buf), "%#B", &this->encoded);
+				snprintf(buf, BUF_LEN, "%#B", &this->encoded);
 			}
 			break;
 		default:
-			snprintf(buf, sizeof(buf), "(unknown ID type: %d)", this->type);
+			snprintf(buf, BUF_LEN, "(unknown ID type: %d)", this->type);
 			break;
 	}
 	if (spec->minus)
@@ -950,6 +1169,13 @@ static private_identification_t *identification_create(id_type_t type)
 			this->public.matches = _matches_dn;
 			this->public.contains_wildcards = _contains_wildcards_dn;
 			break;
+		case ID_IPV4_ADDR:
+		case ID_IPV6_ADDR:
+			this->public.hash = _hash_binary;
+			this->public.equals = _equals_binary;
+			this->public.matches = _matches_range;
+			this->public.contains_wildcards = return_false;
+			break;
 		default:
 			this->public.hash = _hash_binary;
 			this->public.equals = _equals_binary;
@@ -971,6 +1197,10 @@ static private_identification_t* create_from_string_with_prefix_type(char *str)
 	} prefixes[] = {
 		{ "ipv4:",			ID_IPV4_ADDR			},
 		{ "ipv6:",			ID_IPV6_ADDR			},
+		{ "ipv4net:",		ID_IPV4_ADDR_SUBNET		},
+		{ "ipv6net:",		ID_IPV6_ADDR_SUBNET		},
+		{ "ipv4range:",		ID_IPV4_ADDR_RANGE		},
+		{ "ipv6range:",		ID_IPV6_ADDR_RANGE		},
 		{ "rfc822:",		ID_RFC822_ADDR			},
 		{ "email:",			ID_RFC822_ADDR			},
 		{ "userfqdn:",		ID_USER_FQDN			},
@@ -1036,6 +1266,115 @@ static private_identification_t* create_from_string_with_num_type(char *str)
 	return this;
 }
 
+/**
+ * Convert to an IPv4/IPv6 host address, subnet or address range
+ */
+static private_identification_t* create_ip_address_from_string(char *string,
+															   bool is_ipv4)
+{
+	private_identification_t *this;
+	uint8_t encoding[32];
+	uint8_t *str, *pos, *address, *to_address, *netmask;
+	size_t address_size;
+	int bits, bytes, i;
+	bool has_subnet = FALSE, has_range = FALSE;
+
+	address = encoding;
+	address_size = is_ipv4 ? sizeof(struct in_addr) : sizeof(struct in6_addr);
+
+	str = strdup(string);
+	pos = strchr(str, '/');
+	if (pos)
+	{	/* separate IP address from optional netmask */
+
+		*pos = '\0';
+		has_subnet = TRUE;
+	}
+	else
+	{
+		pos = strchr(str, '-');
+		if (pos)
+		{	/* separate lower address from upper address of IP range */
+			*pos = '\0';
+			has_range = TRUE;
+		}
+	}
+
+	if (inet_pton(is_ipv4 ? AF_INET : AF_INET6, str, address) != 1)
+	{
+		free(str);
+		return NULL;
+	}
+
+	if (has_subnet)
+	{	/* is IP subnet */
+		bits = atoi(pos + 1);
+		if (bits > 8 * address_size)
+		{
+			free(str);
+			return NULL;
+		}
+		bytes = bits / 8;
+		bits -= 8 * bytes;
+		netmask = encoding + address_size;
+
+		for (i = 0; i < address_size; i++)
+		{
+			if (bytes)
+			{
+				*netmask = 0xff;
+				bytes--;
+			}
+			else if (bits)
+			{
+				*netmask = 0xff << (8 - bits);
+				bits = 0;
+			}
+			else
+			{
+				*netmask = 0x00;
+			}
+			*address++ &= *netmask++;
+		}
+		this = identification_create(is_ipv4 ? ID_IPV4_ADDR_SUBNET :
+											   ID_IPV6_ADDR_SUBNET);
+		this->encoded = chunk_clone(chunk_create(encoding, 2 * address_size));
+	}
+	else if (has_range)
+	{	/* is IP range */
+		to_address = encoding + address_size;
+
+		if (inet_pton(is_ipv4 ? AF_INET : AF_INET6, pos + 1, to_address) != 1)
+		{
+			free(str);
+			return NULL;
+		}
+		for (i = 0; i < address_size; i++)
+		{
+			if (address[i] != to_address[i])
+			{
+				if (address[i] > to_address[i])
+				{
+					free(str);
+					return NULL;
+				}
+				break;
+			}
+		}
+		this = identification_create(is_ipv4 ? ID_IPV4_ADDR_RANGE :
+											   ID_IPV6_ADDR_RANGE);
+		this->encoded = chunk_clone(chunk_create(encoding, 2 * address_size));
+	}
+	else
+	{	/* is IP host address */
+		this = identification_create(is_ipv4 ? ID_IPV4_ADDR : ID_IPV6_ADDR);
+		this->encoded = chunk_clone(chunk_create(encoding, address_size));
+	}
+	free(str);
+
+	return this;
+}
+
 /*
  * Described in header.
  */
@@ -1093,15 +1432,9 @@ identification_t *identification_create_from_string(char *string)
 		{
 			if (strchr(string, ':') == NULL)
 			{
-				struct in_addr address;
-				chunk_t chunk = {(void*)&address, sizeof(address)};
-
-				if (inet_pton(AF_INET, string, &address) > 0)
-				{	/* is IPv4 */
-					this = identification_create(ID_IPV4_ADDR);
-					this->encoded = chunk_clone(chunk);
-				}
-				else
+				/* IPv4 address or subnet */
+				this = create_ip_address_from_string(string, TRUE);
+				if (!this)
 				{	/* not IPv4, mostly FQDN */
 					this = identification_create(ID_FQDN);
 					this->encoded = chunk_from_str(strdup(string));
@@ -1110,15 +1443,9 @@ identification_t *identification_create_from_string(char *string)
 			}
 			else
 			{
-				struct in6_addr address;
-				chunk_t chunk = {(void*)&address, sizeof(address)};
-
-				if (inet_pton(AF_INET6, string, &address) > 0)
-				{	/* is IPv6 */
-					this = identification_create(ID_IPV6_ADDR);
-					this->encoded = chunk_clone(chunk);
-				}
-				else
+				/* IPv6 address or subnet */
+				this = create_ip_address_from_string(string, FALSE);
+				if (!this)
 				{	/* not IPv4/6 fallback to KEY_ID */
 					this = identification_create(ID_KEY_ID);
 					this->encoded = chunk_from_str(strdup(string));
diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h
index 5f27ba1..51d1324 100644
--- a/src/libstrongswan/utils/identification.h
+++ b/src/libstrongswan/utils/identification.h
@@ -168,6 +168,8 @@ enum id_part_t {
 	ID_PART_RDN_I,
 	/** DN Qualifier RDN of a DN */
 	ID_PART_RDN_DNQ,
+	/** Pseudonym RDN of a DN */
+	ID_PART_RDN_PN,
 	/** UniqueIdentifier RDN of a DN */
 	ID_PART_RDN_ID,
 	/** Locality RDN of a DN */
diff --git a/src/libstrongswan/utils/utils/byteorder.h b/src/libstrongswan/utils/utils/byteorder.h
index 48cf1d5..3ccbad5 100644
--- a/src/libstrongswan/utils/utils/byteorder.h
+++ b/src/libstrongswan/utils/utils/byteorder.h
@@ -44,6 +44,36 @@
 #define BITFIELD5(t, a, b, c, d, e,...)	struct { t e; t d; t c; t b; t a; __VA_ARGS__}
 #endif
 
+#ifndef le32toh
+# if BYTE_ORDER == BIG_ENDIAN
+#  define le32toh(x) __builtin_bswap32(x)
+#  define htole32(x) __builtin_bswap32(x)
+# else
+#  define le32toh(x) (x)
+#  define htole32(x) (x)
+# endif
+#endif
+
+#ifndef le64toh
+# if BYTE_ORDER == BIG_ENDIAN
+#  define le64toh(x) __builtin_bswap64(x)
+#  define htole64(x) __builtin_bswap64(x)
+# else
+#  define le64toh(x) (x)
+#  define htole64(x) (x)
+# endif
+#endif
+
+#ifndef be64toh
+# if BYTE_ORDER == BIG_ENDIAN
+#  define be64toh(x) (x)
+#  define htobe64(x) (x)
+# else
+#  define be64toh(x) __builtin_bswap64(x)
+#  define htobe64(x) __builtin_bswap64(x)
+# endif
+#endif
+
 /**
  * Write a 16-bit host order value in network order to an unaligned address.
  *
@@ -82,21 +112,8 @@ static inline void htoun64(void *network, u_int64_t host)
 {
 	char *unaligned = (char*)network;
 
-#ifdef be64toh
 	host = htobe64(host);
 	memcpy((char*)unaligned, &host, sizeof(host));
-#else
-	u_int32_t high_part, low_part;
-
-	high_part = host >> 32;
-	high_part = htonl(high_part);
-	low_part  = host & 0xFFFFFFFFLL;
-	low_part  = htonl(low_part);
-
-	memcpy(unaligned, &high_part, sizeof(high_part));
-	unaligned += sizeof(high_part);
-	memcpy(unaligned, &low_part, sizeof(low_part));
-#endif
 }
 
 /**
@@ -138,24 +155,37 @@ static inline u_int32_t untoh32(void *network)
 static inline u_int64_t untoh64(void *network)
 {
 	char *unaligned = (char*)network;
-
-#ifdef be64toh
 	u_int64_t tmp;
 
 	memcpy(&tmp, unaligned, sizeof(tmp));
 	return be64toh(tmp);
-#else
-	u_int32_t high_part, low_part;
+}
 
-	memcpy(&high_part, unaligned, sizeof(high_part));
-	unaligned += sizeof(high_part);
-	memcpy(&low_part, unaligned, sizeof(low_part));
+/**
+ * Read a 32-bit value in little-endian order from unaligned address.
+ *
+ * @param p			unaligned address to read little endian value from
+ * @return			host order value
+ */
+static inline u_int32_t uletoh32(void *p)
+{
+	u_int32_t ret;
 
-	high_part = ntohl(high_part);
-	low_part  = ntohl(low_part);
+	memcpy(&ret, p, sizeof(ret));
+	ret = le32toh(ret);
+	return ret;
+}
 
-	return (((u_int64_t)high_part) << 32) + low_part;
-#endif
+/**
+ * Write a 32-bit value in little-endian to an unaligned address.
+ *
+ * @param p			host order 32-bit value
+ * @param v			unaligned address to write little endian value to
+ */
+static inline void htoule32(void *p, u_int32_t v)
+{
+	v = htole32(v);
+	memcpy(p, &v, sizeof(v));
 }
 
 #endif /** BYTEORDER_H_ @} */
diff --git a/src/libtls/Makefile.in b/src/libtls/Makefile.in
index e6c23d9..8d16059 100644
--- a/src/libtls/Makefile.in
+++ b/src/libtls/Makefile.in
@@ -465,6 +465,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libtls/tests/Makefile.in b/src/libtls/tests/Makefile.in
index 7d5b377..e57a95f 100644
--- a/src/libtls/tests/Makefile.in
+++ b/src/libtls/tests/Makefile.in
@@ -410,6 +410,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libtls/tls_peer.c b/src/libtls/tls_peer.c
index 000dda4..8087e2e 100644
--- a/src/libtls/tls_peer.c
+++ b/src/libtls/tls_peer.c
@@ -320,7 +320,8 @@ static public_key_t *find_public_key(private_tls_peer_t *this)
 	if (cert)
 	{
 		enumerator = lib->credmgr->create_public_enumerator(lib->credmgr,
-						KEY_ANY, cert->get_subject(cert), this->server_auth);
+											KEY_ANY, cert->get_subject(cert),
+											this->server_auth, TRUE);
 		while (enumerator->enumerate(enumerator, &current, &auth))
 		{
 			found = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
diff --git a/src/libtls/tls_server.c b/src/libtls/tls_server.c
index f9295a1..cfbe020 100644
--- a/src/libtls/tls_server.c
+++ b/src/libtls/tls_server.c
@@ -548,7 +548,7 @@ static status_t process_cert_verify(private_tls_server_t *this,
 	bio_reader_t *sig;
 
 	enumerator = lib->credmgr->create_public_enumerator(lib->credmgr,
-										KEY_ANY, this->peer, this->peer_auth);
+									KEY_ANY, this->peer, this->peer_auth, TRUE);
 	while (enumerator->enumerate(enumerator, &public, &auth))
 	{
 		sig = bio_reader_create(reader->peek(reader));
diff --git a/src/libtnccs/Makefile.in b/src/libtnccs/Makefile.in
index dc8c1b8..85d2581 100644
--- a/src/libtnccs/Makefile.in
+++ b/src/libtnccs/Makefile.in
@@ -470,6 +470,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libtnccs/plugins/tnc_imc/Makefile.in b/src/libtnccs/plugins/tnc_imc/Makefile.in
index 3641bdf..963e1f0 100644
--- a/src/libtnccs/plugins/tnc_imc/Makefile.in
+++ b/src/libtnccs/plugins/tnc_imc/Makefile.in
@@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libtnccs/plugins/tnc_imv/Makefile.in b/src/libtnccs/plugins/tnc_imv/Makefile.in
index c4b1bee..f77db91 100644
--- a/src/libtnccs/plugins/tnc_imv/Makefile.in
+++ b/src/libtnccs/plugins/tnc_imv/Makefile.in
@@ -419,6 +419,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libtnccs/plugins/tnc_tnccs/Makefile.in b/src/libtnccs/plugins/tnc_tnccs/Makefile.in
index 5b01e31..577f537 100644
--- a/src/libtnccs/plugins/tnc_tnccs/Makefile.in
+++ b/src/libtnccs/plugins/tnc_tnccs/Makefile.in
@@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libtnccs/plugins/tnccs_11/Makefile.in b/src/libtnccs/plugins/tnccs_11/Makefile.in
index e0c039a..ec5de0f 100644
--- a/src/libtnccs/plugins/tnccs_11/Makefile.in
+++ b/src/libtnccs/plugins/tnccs_11/Makefile.in
@@ -428,6 +428,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libtnccs/plugins/tnccs_20/Makefile.in b/src/libtnccs/plugins/tnccs_20/Makefile.in
index 17d997f..5037a95 100644
--- a/src/libtnccs/plugins/tnccs_20/Makefile.in
+++ b/src/libtnccs/plugins/tnccs_20/Makefile.in
@@ -431,6 +431,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20.c b/src/libtnccs/plugins/tnccs_20/tnccs_20.c
index a1a9573..35d2978 100644
--- a/src/libtnccs/plugins/tnccs_20/tnccs_20.c
+++ b/src/libtnccs/plugins/tnccs_20/tnccs_20.c
@@ -126,6 +126,24 @@ struct private_tnccs_20_t {
 
 };
 
+METHOD(tls_t, is_complete, bool,
+	private_tnccs_20_t *this)
+{
+	TNC_IMV_Action_Recommendation rec;
+	TNC_IMV_Evaluation_Result eval;
+	tnccs_20_server_t *tnc_server;
+
+	if (this->tnc_server)
+	{
+		tnc_server = (tnccs_20_server_t*)this->tnc_server;
+		if (tnc_server->have_recommendation(tnc_server, &rec, &eval))
+		{
+			return this->callback ? this->callback(rec, eval) : TRUE;
+		}
+	}
+	return FALSE;
+}
+
 METHOD(tnccs_t, send_msg, TNC_Result,
 	private_tnccs_20_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id,
 							  TNC_UInt32 msg_flags,
@@ -269,6 +287,7 @@ METHOD(tls_t, process, status_t,
 		/* Suppress a successful CLOSE batch coming from the TNC server */
 		if (status == SUCCESS)
 		{
+			is_complete(this);
 			status = NEED_MORE;
 		}
 	}
@@ -359,25 +378,6 @@ METHOD(tls_t, get_purpose, tls_purpose_t,
 	return TLS_PURPOSE_EAP_TNC;
 }
 
-METHOD(tls_t, is_complete, bool,
-	private_tnccs_20_t *this)
-{
-	TNC_IMV_Action_Recommendation rec;
-	TNC_IMV_Evaluation_Result eval;
-
-	if (this->tnc_server)
-	{
-		tnccs_20_server_t *tnc_server;
-
-		tnc_server = (tnccs_20_server_t*)this->tnc_server;
-		if (tnc_server->have_recommendation(tnc_server, &rec, &eval))
-		{
-			return this->callback ? this->callback(rec, eval) : TRUE;
-		}
-	}
-	return FALSE;
-}
-
 METHOD(tls_t, get_eap_msk, chunk_t,
 	private_tnccs_20_t *this)
 {
diff --git a/src/libtnccs/plugins/tnccs_dynamic/Makefile.in b/src/libtnccs/plugins/tnccs_dynamic/Makefile.in
index 3f21a22..949532a 100644
--- a/src/libtnccs/plugins/tnccs_dynamic/Makefile.in
+++ b/src/libtnccs/plugins/tnccs_dynamic/Makefile.in
@@ -418,6 +418,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/libtncif/Makefile.in b/src/libtncif/Makefile.in
index 010fadc..4be7ae1 100644
--- a/src/libtncif/Makefile.in
+++ b/src/libtncif/Makefile.in
@@ -380,6 +380,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/manager/Makefile.in b/src/manager/Makefile.in
index 500220a..9beaab0 100644
--- a/src/manager/Makefile.in
+++ b/src/manager/Makefile.in
@@ -432,6 +432,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/medsrv/Makefile.in b/src/medsrv/Makefile.in
index 42830e1..c367841 100644
--- a/src/medsrv/Makefile.in
+++ b/src/medsrv/Makefile.in
@@ -421,6 +421,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/pki/Makefile.am b/src/pki/Makefile.am
index a3da0ab..261e41c 100644
--- a/src/pki/Makefile.am
+++ b/src/pki/Makefile.am
@@ -17,7 +17,10 @@ pki_SOURCES = pki.c pki.h command.c command.h \
 	commands/signcrl.c \
 	commands/verify.c
 
-pki_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
+pki_LDADD = \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(PTHREADLIB) $(DLLIB)
+
 pki.o :	$(top_builddir)/config.status
 
 AM_CPPFLAGS = \
diff --git a/src/pki/Makefile.in b/src/pki/Makefile.in
index b4829f7..4b206c9 100644
--- a/src/pki/Makefile.in
+++ b/src/pki/Makefile.in
@@ -111,7 +111,9 @@ am_pki_OBJECTS = pki.$(OBJEXT) command.$(OBJEXT) \
 	commands/self.$(OBJEXT) commands/signcrl.$(OBJEXT) \
 	commands/verify.$(OBJEXT)
 pki_OBJECTS = $(am_pki_OBJECTS)
-pki_DEPENDENCIES = $(top_builddir)/src/libstrongswan/libstrongswan.la
+am__DEPENDENCIES_1 =
+pki_DEPENDENCIES = $(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 AM_V_lt = $(am__v_lt_ at AM_V@)
 am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
 am__v_lt_0 = --silent
@@ -431,6 +433,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -460,7 +464,10 @@ pki_SOURCES = pki.c pki.h command.c command.h \
 	commands/signcrl.c \
 	commands/verify.c
 
-pki_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
+pki_LDADD = \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(PTHREADLIB) $(DLLIB)
+
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
 	-DPLUGINS=\""${pki_plugins}\""
@@ -919,6 +926,7 @@ uninstall-am: uninstall-binPROGRAMS
 	mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
 	uninstall-am uninstall-binPROGRAMS
 
+
 pki.o :	$(top_builddir)/config.status
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/pki/command.c b/src/pki/command.c
index 13e8140..ce704db 100644
--- a/src/pki/command.c
+++ b/src/pki/command.c
@@ -172,6 +172,15 @@ void command_register(command_t command)
 				"options",	'+', 1, "read command line options from file"
 			};
 		}
+		for (i = 0; cmds[registered].line[i]; i++)
+		{
+			if (i == MAX_LINES - 1)
+			{
+				fprintf(stderr, "command '%s' specifies too many usage summary "
+						"lines, please increase MAX_LINES\n", command.cmd);
+				break;
+			}
+		}
 	}
 	registered++;
 }
@@ -208,7 +217,7 @@ int command_usage(char *error)
 	}
 	else
 	{
-		for (i = 0; cmds[active].line[i]; i++)
+		for (i = 0; i < MAX_LINES && cmds[active].line[i]; i++)
 		{
 			if (i == 0)
 			{
diff --git a/src/pki/command.h b/src/pki/command.h
index e55c579..449252e 100644
--- a/src/pki/command.h
+++ b/src/pki/command.h
@@ -34,7 +34,7 @@
 /**
  * Maximum number of usage summary lines (+1)
  */
-#define MAX_LINES 10
+#define MAX_LINES 11
 
 typedef struct command_t command_t;
 typedef struct command_option_t command_option_t;
diff --git a/src/pki/commands/print.c b/src/pki/commands/print.c
index fa69de1..c367a21 100644
--- a/src/pki/commands/print.c
+++ b/src/pki/commands/print.c
@@ -2,6 +2,9 @@
  * Copyright (C) 2010 Martin Willi
  * Copyright (C) 2010 revosec AG
  *
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR 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
@@ -15,540 +18,37 @@
 
 #include "pki.h"
 
-#include <asn1/asn1.h>
-#include <asn1/oid.h>
 #include <credentials/certificates/certificate.h>
-#include <credentials/certificates/x509.h>
-#include <credentials/certificates/crl.h>
-#include <credentials/certificates/ac.h>
-#include <selectors/traffic_selector.h>
+#include <credentials/certificates/certificate_printer.h>
 
-#include <time.h>
 #include <errno.h>
 
 /**
- * Print public key information
- */
-static void print_pubkey(public_key_t *key)
-{
-	chunk_t chunk;
-	key_type_t type;
-
-	type = key->get_type(key);
-	printf("pubkey:    %N %d bits%s\n", key_type_names, type,
-			key->get_keysize(key), (type == KEY_BLISS) ? " strength" : "");
-
-	if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &chunk))
-	{
-		printf("keyid:     %#B\n", &chunk);
-	}
-	if (key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &chunk))
-	{
-		printf("subjkey:   %#B\n", &chunk);
-	}
-}
-
-/**
  * Print private key information
  */
 static void print_key(private_key_t *key)
 {
 	public_key_t *public;
+	chunk_t chunk;
 
 	public = key->get_public_key(key);
 	if (public)
 	{
-		printf("private key with:\n");
-		print_pubkey(public);
-		public->destroy(public);
-	}
-	else
-	{
-		printf("extracting public from private key failed\n");
-	}
-}
-
-/**
- * Get a prefix for a named constraint identity type
- */
-static char* get_type_pfx(identification_t *id)
-{
-	switch (id->get_type(id))
-	{
-		case ID_RFC822_ADDR:
-			return "email:";
-		case ID_FQDN:
-			return "dns:";
-		default:
-			return "";
-	}
-}
-
-/**
- * Print X509 specific certificate information
- */
-static void print_x509(x509_t *x509)
-{
-	enumerator_t *enumerator;
-	identification_t *id;
-	traffic_selector_t *block;
-	chunk_t chunk;
-	bool first;
-	char *uri;
-	int len, explicit, inhibit;
-	x509_flag_t flags;
-	x509_cdp_t *cdp;
-	x509_cert_policy_t *policy;
-	x509_policy_mapping_t *mapping;
-
-	chunk = chunk_skip_zero(x509->get_serial(x509));
-	printf("serial:    %#B\n", &chunk);
-
-	first = TRUE;
-	enumerator = x509->create_subjectAltName_enumerator(x509);
-	while (enumerator->enumerate(enumerator, &id))
-	{
-		if (first)
-		{
-			printf("altNames:  ");
-			first = FALSE;
-		}
-		else
-		{
-			printf(", ");
-		}
-		printf("%Y", id);
-	}
-	if (!first)
-	{
-		printf("\n");
-	}
-	enumerator->destroy(enumerator);
-
-	flags = x509->get_flags(x509);
-	printf("flags:     ");
-	if (flags & X509_CA)
-	{
-		printf("CA ");
-	}
-	if (flags & X509_CRL_SIGN)
-	{
-		printf("CRLSign ");
-	}
-	if (flags & X509_AA)
-	{
-		printf("AA ");
-	}
-	if (flags & X509_OCSP_SIGNER)
-	{
-		printf("OCSP ");
-	}
-	if (flags & X509_AA)
-	{
-		printf("AA ");
-	}
-	if (flags & X509_SERVER_AUTH)
-	{
-		printf("serverAuth ");
-	}
-	if (flags & X509_CLIENT_AUTH)
-	{
-		printf("clientAuth ");
-	}
-	if (flags & X509_IKE_INTERMEDIATE)
-	{
-		printf("iKEIntermediate ");
-	}
-	if (flags & X509_MS_SMARTCARD_LOGON)
-	{
-		printf("msSmartcardLogon ");
-	}
-	if (flags & X509_SELF_SIGNED)
-	{
-		printf("self-signed ");
-	}
-	printf("\n");
-
-	first = TRUE;
-	enumerator = x509->create_crl_uri_enumerator(x509);
-	while (enumerator->enumerate(enumerator, &cdp))
-	{
-		if (first)
-		{
-			printf("CRL URIs:  %s", cdp->uri);
-			first = FALSE;
-		}
-		else
-		{
-			printf("           %s", cdp->uri);
-		}
-		if (cdp->issuer)
-		{
-			printf(" (CRL issuer: %Y)", cdp->issuer);
-		}
-		printf("\n");
-	}
-	enumerator->destroy(enumerator);
-
-	first = TRUE;
-	enumerator = x509->create_ocsp_uri_enumerator(x509);
-	while (enumerator->enumerate(enumerator, &uri))
-	{
-		if (first)
-		{
-			printf("OCSP URIs: %s\n", uri);
-			first = FALSE;
-		}
-		else
-		{
-			printf("           %s\n", uri);
-		}
-	}
-	enumerator->destroy(enumerator);
-
-	len = x509->get_constraint(x509, X509_PATH_LEN);
-	if (len != X509_NO_CONSTRAINT)
-	{
-		printf("pathlen:   %d\n", len);
-	}
-
-	first = TRUE;
-	enumerator = x509->create_name_constraint_enumerator(x509, TRUE);
-	while (enumerator->enumerate(enumerator, &id))
-	{
-		if (first)
-		{
-			printf("Permitted NameConstraints:\n");
-			first = FALSE;
-		}
-		printf("           %s%Y\n", get_type_pfx(id), id);
-	}
-	enumerator->destroy(enumerator);
-	first = TRUE;
-	enumerator = x509->create_name_constraint_enumerator(x509, FALSE);
-	while (enumerator->enumerate(enumerator, &id))
-	{
-		if (first)
-		{
-			printf("Excluded NameConstraints:\n");
-			first = FALSE;
-		}
-		printf("           %s%Y\n", get_type_pfx(id), id);
-	}
-	enumerator->destroy(enumerator);
-
-	first = TRUE;
-	enumerator = x509->create_cert_policy_enumerator(x509);
-	while (enumerator->enumerate(enumerator, &policy))
-	{
-		char *oid;
-
-		if (first)
-		{
-			printf("CertificatePolicies:\n");
-			first = FALSE;
-		}
-		oid = asn1_oid_to_string(policy->oid);
-		if (oid)
-		{
-			printf("           %s\n", oid);
-			free(oid);
-		}
-		else
-		{
-			printf("           %#B\n", &policy->oid);
-		}
-		if (policy->cps_uri)
-		{
-			printf("             CPS: %s\n", policy->cps_uri);
-		}
-		if (policy->unotice_text)
-		{
-			printf("             Notice: %s\n", policy->unotice_text);
-
-		}
-	}
-	enumerator->destroy(enumerator);
-
-	first = TRUE;
-	enumerator = x509->create_policy_mapping_enumerator(x509);
-	while (enumerator->enumerate(enumerator, &mapping))
-	{
-		char *issuer_oid, *subject_oid;
-
-		if (first)
-		{
-			printf("PolicyMappings:\n");
-			first = FALSE;
-		}
-		issuer_oid = asn1_oid_to_string(mapping->issuer);
-		subject_oid = asn1_oid_to_string(mapping->subject);
-		printf("           %s => %s\n", issuer_oid, subject_oid);
-		free(issuer_oid);
-		free(subject_oid);
-	}
-	enumerator->destroy(enumerator);
-
-	explicit = x509->get_constraint(x509, X509_REQUIRE_EXPLICIT_POLICY);
-	inhibit = x509->get_constraint(x509, X509_INHIBIT_POLICY_MAPPING);
-	len = x509->get_constraint(x509, X509_INHIBIT_ANY_POLICY);
-
-	if (explicit != X509_NO_CONSTRAINT || inhibit != X509_NO_CONSTRAINT ||
-		len != X509_NO_CONSTRAINT)
-	{
-		printf("PolicyConstraints:\n");
-		if (explicit != X509_NO_CONSTRAINT)
-		{
-			printf("           requireExplicitPolicy: %d\n", explicit);
-		}
-		if (inhibit != X509_NO_CONSTRAINT)
-		{
-			printf("           inhibitPolicyMapping: %d\n", inhibit);
-		}
-		if (len != X509_NO_CONSTRAINT)
-		{
-			printf("           inhibitAnyPolicy: %d\n", len);
-		}
-	}
-
-	chunk = x509->get_authKeyIdentifier(x509);
-	if (chunk.ptr)
-	{
-		printf("authkeyId: %#B\n", &chunk);
-	}
-
-	chunk = x509->get_subjectKeyIdentifier(x509);
-	if (chunk.ptr)
-	{
-		printf("subjkeyId: %#B\n", &chunk);
-	}
-	if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
-	{
-		first = TRUE;
-		printf("addresses: ");
-		enumerator = x509->create_ipAddrBlock_enumerator(x509);
-		while (enumerator->enumerate(enumerator, &block))
-		{
-			if (first)
-			{
-				first = FALSE;
-			}
-			else
-			{
-				printf(", ");
-			}
-			printf("%R", block);
-		}
-		enumerator->destroy(enumerator);
-		printf("\n");
-	}
-}
-
-/**
- * Print CRL specific information
- */
-static void print_crl(crl_t *crl)
-{
-	enumerator_t *enumerator;
-	time_t ts;
-	crl_reason_t reason;
-	chunk_t chunk;
-	int count = 0;
-	bool first;
-	char buf[64];
-	struct tm tm;
-	x509_cdp_t *cdp;
-
-	chunk = chunk_skip_zero(crl->get_serial(crl));
-	printf("serial:    %#B\n", &chunk);
-
-	if (crl->is_delta_crl(crl, &chunk))
-	{
-		chunk = chunk_skip_zero(chunk);
-		printf("delta CRL: for serial %#B\n", &chunk);
-	}
-	chunk = crl->get_authKeyIdentifier(crl);
-	printf("authKeyId: %#B\n", &chunk);
-
-	first = TRUE;
-	enumerator = crl->create_delta_crl_uri_enumerator(crl);
-	while (enumerator->enumerate(enumerator, &cdp))
-	{
-		if (first)
-		{
-			printf("freshest:  %s", cdp->uri);
-			first = FALSE;
-		}
-		else
-		{
-			printf("           %s", cdp->uri);
-		}
-		if (cdp->issuer)
-		{
-			printf(" (CRL issuer: %Y)", cdp->issuer);
-		}
-		printf("\n");
-	}
-	enumerator->destroy(enumerator);
-
-	enumerator = crl->create_enumerator(crl);
-	while (enumerator->enumerate(enumerator, &chunk, &ts, &reason))
-	{
-		count++;
-	}
-	enumerator->destroy(enumerator);
-
-	printf("%d revoked certificate%s%s\n", count,
-		   count == 1 ? "" : "s", count ? ":" : "");
-	enumerator = crl->create_enumerator(crl);
-	while (enumerator->enumerate(enumerator, &chunk, &ts, &reason))
-	{
-		chunk = chunk_skip_zero(chunk);
-		localtime_r(&ts, &tm);
-		strftime(buf, sizeof(buf), "%F %T", &tm);
-		printf("    %#B %N %s\n", &chunk, crl_reason_names, reason, buf);
-		count++;
-	}
-	enumerator->destroy(enumerator);
-}
-
-/**
- * Print AC specific information
- */
-static void print_ac(ac_t *ac)
-{
-	ac_group_type_t type;
-	identification_t *id;
-	enumerator_t *groups;
-	chunk_t chunk;
-	bool first = TRUE;
-
-	chunk = chunk_skip_zero(ac->get_serial(ac));
-	printf("serial:    %#B\n", &chunk);
-
-	id = ac->get_holderIssuer(ac);
-	if (id)
-	{
-		printf("hissuer:  \"%Y\"\n", id);
-	}
-	chunk = chunk_skip_zero(ac->get_holderSerial(ac));
-	if (chunk.ptr)
-	{
-		printf("hserial:   %#B\n", &chunk);
-	}
-	groups = ac->create_group_enumerator(ac);
-	while (groups->enumerate(groups, &type, &chunk))
-	{
-		int oid;
-		char *str;
-
-		if (first)
+		printf("  privkey:   %N %d bits\n", key_type_names,
+			   public->get_type(public), public->get_keysize(public));
+		if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &chunk))
 		{
-			printf("groups:    ");
-			first = FALSE;
+			printf("  keyid:     %#B\n", &chunk);
 		}
-		else
+		if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk))
 		{
-			printf("           ");
+			printf("  subjkey:   %#B\n", &chunk);
 		}
-		switch (type)
-		{
-			case AC_GROUP_TYPE_STRING:
-				printf("%.*s", (int)chunk.len, chunk.ptr);
-				break;
-			case AC_GROUP_TYPE_OID:
-				oid = asn1_known_oid(chunk);
-				if (oid == OID_UNKNOWN)
-				{
-					str = asn1_oid_to_string(chunk);
-					if (str)
-					{
-						printf("%s", str);
-						free(str);
-					}
-					else
-					{
-						printf("OID:%#B", &chunk);
-					}
-				}
-				else
-				{
-					printf("%s", oid_names[oid].name);
-				}
-				break;
-			case AC_GROUP_TYPE_OCTETS:
-				printf("%#B", &chunk);
-				break;
-		}
-		printf("\n");
-	}
-	groups->destroy(groups);
-
-	chunk = ac->get_authKeyIdentifier(ac);
-	if (chunk.ptr)
-	{
-		printf("authkey:  %#B\n", &chunk);
-	}
-}
-
-/**
- * Print certificate information
- */
-static void print_cert(certificate_t *cert)
-{
-	time_t now, notAfter, notBefore;
-	public_key_t *key;
-
-	now = time(NULL);
-
-	printf("cert:      %N\n", certificate_type_names, cert->get_type(cert));
-	if (cert->get_type(cert) != CERT_X509_CRL)
-	{
-		printf("subject:  \"%Y\"\n", cert->get_subject(cert));
-	}
-	printf("issuer:   \"%Y\"\n", cert->get_issuer(cert));
-
-	cert->get_validity(cert, &now, &notBefore, &notAfter);
-	printf("validity:  not before %T, ", &notBefore, FALSE);
-	if (now < notBefore)
-	{
-		printf("not valid yet (valid in %V)\n", &now, &notBefore);
-	}
-	else
-	{
-		printf("ok\n");
-	}
-	printf("           not after  %T, ", &notAfter, FALSE);
-	if (now > notAfter)
-	{
-		printf("expired (%V ago)\n", &now, &notAfter);
+		public->destroy(public);
 	}
 	else
 	{
-		printf("ok (expires in %V)\n", &now, &notAfter);
-	}
-
-	switch (cert->get_type(cert))
-	{
-		case CERT_X509:
-			print_x509((x509_t*)cert);
-			break;
-		case CERT_X509_CRL:
-			print_crl((crl_t*)cert);
-			break;
-		case CERT_X509_AC:
-			print_ac((ac_t*)cert);
-			break;
-		default:
-			printf("parsing certificate subtype %N not implemented\n",
-				   certificate_type_names, cert->get_type(cert));
-			break;
-	}
-	key = cert->get_public_key(cert);
-	if (key)
-	{
-		print_pubkey(key);
-		key->destroy(key);
+		printf("extracting public from private key failed\n");
 	}
 }
 
@@ -586,8 +86,8 @@ static int print()
 				}
 				else if (streq(arg, "pub"))
 				{
-					type = CRED_PUBLIC_KEY;
-					subtype = KEY_ANY;
+					type = CRED_CERTIFICATE;
+					subtype = CERT_TRUSTED_PUBKEY;
 				}
 				else if (streq(arg, "rsa-priv"))
 				{
@@ -647,17 +147,13 @@ static int print()
 	if (type == CRED_CERTIFICATE)
 	{
 		certificate_t *cert = (certificate_t*)cred;
+		certificate_printer_t *printer;
 
-		print_cert(cert);
+		printer = certificate_printer_create(stdout, TRUE, FALSE);
+		printer->print(printer, cert, FALSE);
+		printer->destroy(printer);
 		cert->destroy(cert);
 	}
-	if (type == CRED_PUBLIC_KEY)
-	{
-		public_key_t *key = (public_key_t*)cred;
-
-		print_pubkey(key);
-		key->destroy(key);
-	}
 	if (type == CRED_PRIVATE_KEY)
 	{
 		private_key_t *key = (private_key_t*)cred;
@@ -665,6 +161,7 @@ static int print()
 		print_key(key);
 		key->destroy(key);
 	}
+
 	return 0;
 }
 
diff --git a/src/pki/man/Makefile.in b/src/pki/man/Makefile.in
index 62942d1..e612309 100644
--- a/src/pki/man/Makefile.in
+++ b/src/pki/man/Makefile.in
@@ -370,6 +370,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/pool/Makefile.am b/src/pool/Makefile.am
index 5ae624b..1513bbf 100644
--- a/src/pool/Makefile.am
+++ b/src/pool/Makefile.am
@@ -10,13 +10,11 @@ pool.o :	$(top_builddir)/config.status
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-I$(top_srcdir)/src/libcharon \
 	-DPLUGINS=\""${pool_plugins}\""
 
 pool_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
 	$(top_builddir)/src/libcharon/libcharon.la
 
 endif USE_ATTR_SQL
diff --git a/src/pool/Makefile.in b/src/pool/Makefile.in
index b955754..3d9adb1 100644
--- a/src/pool/Makefile.in
+++ b/src/pool/Makefile.in
@@ -109,7 +109,6 @@ am__pool_SOURCES_DIST = pool.c pool_attributes.c pool_attributes.h \
 @USE_ATTR_SQL_TRUE@	pool_usage.$(OBJEXT)
 pool_OBJECTS = $(am_pool_OBJECTS)
 @USE_ATTR_SQL_TRUE at pool_DEPENDENCIES = $(top_builddir)/src/libstrongswan/libstrongswan.la \
- at USE_ATTR_SQL_TRUE@	$(top_builddir)/src/libhydra/libhydra.la \
 @USE_ATTR_SQL_TRUE@	$(top_builddir)/src/libcharon/libcharon.la
 AM_V_lt = $(am__v_lt_ at AM_V@)
 am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
@@ -416,6 +415,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -435,13 +436,11 @@ xml_LIBS = @xml_LIBS@
 
 @USE_ATTR_SQL_TRUE at AM_CPPFLAGS = \
 @USE_ATTR_SQL_TRUE@	-I$(top_srcdir)/src/libstrongswan \
- at USE_ATTR_SQL_TRUE@	-I$(top_srcdir)/src/libhydra \
 @USE_ATTR_SQL_TRUE@	-I$(top_srcdir)/src/libcharon \
 @USE_ATTR_SQL_TRUE@	-DPLUGINS=\""${pool_plugins}\""
 
 @USE_ATTR_SQL_TRUE at pool_LDADD = \
 @USE_ATTR_SQL_TRUE@	$(top_builddir)/src/libstrongswan/libstrongswan.la \
- at USE_ATTR_SQL_TRUE@	$(top_builddir)/src/libhydra/libhydra.la \
 @USE_ATTR_SQL_TRUE@	$(top_builddir)/src/libcharon/libcharon.la
 
 templatesdir = $(pkgdatadir)/templates/database/sql
diff --git a/src/pt-tls-client/Makefile.in b/src/pt-tls-client/Makefile.in
index a02db98..2ab3cbf 100644
--- a/src/pt-tls-client/Makefile.in
+++ b/src/pt-tls-client/Makefile.in
@@ -385,6 +385,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/scepclient/Makefile.am b/src/scepclient/Makefile.am
index b3beb1b..1311672 100644
--- a/src/scepclient/Makefile.am
+++ b/src/scepclient/Makefile.am
@@ -6,7 +6,6 @@ scepclient.o :	$(top_builddir)/config.status
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\" \
 	-DPLUGINS=\""${scepclient_plugins}\""
 
diff --git a/src/scepclient/Makefile.in b/src/scepclient/Makefile.in
index bcc70cb..141db69 100644
--- a/src/scepclient/Makefile.in
+++ b/src/scepclient/Makefile.in
@@ -412,6 +412,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -430,7 +432,6 @@ scepclient.c scep.c scep.h
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\" \
 	-DPLUGINS=\""${scepclient_plugins}\""
 
diff --git a/src/starter/Android.mk b/src/starter/Android.mk
index 8c5d1a9..e882cc7 100644
--- a/src/starter/Android.mk
+++ b/src/starter/Android.mk
@@ -14,7 +14,6 @@ LOCAL_SRC_FILES := $(filter %.c,$(starter_SOURCES))
 # build starter ----------------------------------------------------------------
 
 LOCAL_C_INCLUDES += \
-	$(strongswan_PATH)/src/libhydra \
 	$(strongswan_PATH)/src/libstrongswan \
 	$(strongswan_PATH)/src/starter \
 	$(strongswan_PATH)/src/stroke
@@ -33,7 +32,7 @@ LOCAL_PRELINK_MODULE := false
 
 LOCAL_REQUIRED_MODULES := stroke
 
-LOCAL_SHARED_LIBRARIES += libstrongswan libhydra
+LOCAL_SHARED_LIBRARIES += libstrongswan
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/src/starter/Makefile.am b/src/starter/Makefile.am
index 7f5d1ca..8341ca3 100644
--- a/src/starter/Makefile.am
+++ b/src/starter/Makefile.am
@@ -15,7 +15,7 @@ parser/parser.y parser/lexer.l parser/conf_parser.c parser/conf_parser.h
 AM_CPPFLAGS = \
 	-I${linux_headers} \
 	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
+	-I$(top_srcdir)/src/libcharon \
 	-I$(top_srcdir)/src/starter \
 	-I$(top_srcdir)/src/stroke \
 	-DIPSEC_DIR=\"${ipsecdir}\" \
@@ -32,7 +32,7 @@ AM_YFLAGS = -v -d
 
 starter_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
+	$(top_builddir)/src/libcharon/libcharon.la \
 	libstarter.la \
 	$(SOCKLIB) $(PTHREADLIB)
 
diff --git a/src/starter/Makefile.in b/src/starter/Makefile.in
index 3166cc5..31e0e9d 100644
--- a/src/starter/Makefile.in
+++ b/src/starter/Makefile.in
@@ -123,7 +123,7 @@ starter_OBJECTS = $(am_starter_OBJECTS)
 am__DEPENDENCIES_1 =
 starter_DEPENDENCIES =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la libstarter.la \
+	$(top_builddir)/src/libcharon/libcharon.la libstarter.la \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 AM_V_P = $(am__v_P_ at AM_V@)
 am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
@@ -457,6 +457,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -484,7 +486,7 @@ libstarter_la_SOURCES = \
 parser/parser.y parser/lexer.l parser/conf_parser.c parser/conf_parser.h
 
 AM_CPPFLAGS = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/starter \
+	-I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/starter \
 	-I$(top_srcdir)/src/stroke -DIPSEC_DIR=\"${ipsecdir}\" \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\" -DIPSEC_PIDDIR=\"${piddir}\" \
 	-DIPSEC_EAPDIR=\"${eapdir}\" \
@@ -496,7 +498,7 @@ AM_CPPFLAGS = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
 AM_YFLAGS = -v -d
 starter_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.la \
+	$(top_builddir)/src/libcharon/libcharon.la \
 	libstarter.la \
 	$(SOCKLIB) $(PTHREADLIB)
 
diff --git a/src/starter/confread.c b/src/starter/confread.c
index c3a0ac0..897aa42 100644
--- a/src/starter/confread.c
+++ b/src/starter/confread.c
@@ -40,8 +40,8 @@
 #define SA_REPLACEMENT_RETRIES_DEFAULT   3
 #define SA_REPLAY_WINDOW_DEFAULT        -1 /* use charon.replay_window */
 
-static const char ike_defaults[] = "aes128-sha1-modp2048,3des-sha1-modp1536";
-static const char esp_defaults[] = "aes128-sha1,3des-sha1";
+static const char ike_defaults[] = "aes128-sha256-modp3072";
+static const char esp_defaults[] = "aes128-sha256";
 
 static const char firewall_defaults[] = IPSEC_SCRIPT " _updown iptables";
 
diff --git a/src/starter/netkey.c b/src/starter/netkey.c
index 3eb6973..b150d3e 100644
--- a/src/starter/netkey.c
+++ b/src/starter/netkey.c
@@ -17,7 +17,6 @@
 #include <stdlib.h>
 
 #include <library.h>
-#include <hydra.h>
 #include <utils/debug.h>
 
 #include "files.h"
diff --git a/src/starter/starter.c b/src/starter/starter.c
index ab1ebdd..45c28d3 100644
--- a/src/starter/starter.c
+++ b/src/starter/starter.c
@@ -33,7 +33,6 @@
 #include <pthread.h>
 
 #include <library.h>
-#include <hydra.h>
 #include <utils/backtrace.h>
 #include <threading/thread.h>
 #include <utils/debug.h>
@@ -427,9 +426,6 @@ int main (int argc, char **argv)
 	library_init(NULL, "starter");
 	atexit(library_deinit);
 
-	libhydra_init();
-	atexit(libhydra_deinit);
-
 	/* parse command line */
 	for (i = 1; i < argc; i++)
 	{
diff --git a/src/starter/tests/Makefile.in b/src/starter/tests/Makefile.in
index b261255..58daacf 100644
--- a/src/starter/tests/Makefile.in
+++ b/src/starter/tests/Makefile.in
@@ -410,6 +410,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/stroke/Makefile.in b/src/stroke/Makefile.in
index c32ebf9..e7bfd9d 100644
--- a/src/stroke/Makefile.in
+++ b/src/stroke/Makefile.in
@@ -384,6 +384,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c
index 2dfb66d..6571815 100644
--- a/src/stroke/stroke.c
+++ b/src/stroke/stroke.c
@@ -279,7 +279,7 @@ static int list_flags[] = {
 	LIST_ALL
 };
 
-static int list(stroke_keyword_t kw, int utc)
+static int list(stroke_keyword_t kw, bool utc)
 {
 	stroke_msg_t *msg;
 
@@ -433,9 +433,9 @@ static int usage(char *error)
 	fprintf(out, "  Show extended status information without blocking:\n");
 	fprintf(out, "    stroke statusall-nb\n");
 	fprintf(out, "  Show list of authority and attribute certificates:\n");
-	fprintf(out, "    stroke listcacerts|listocspcerts|listaacerts|listacerts\n");
+	fprintf(out, "    stroke listcacerts|listocspcerts|listaacerts|listacerts [--utc]\n");
 	fprintf(out, "  Show list of end entity certificates, ca info records  and crls:\n");
-	fprintf(out, "    stroke listcerts|listcainfos|listcrls|listall\n");
+	fprintf(out, "    stroke listcerts|listcainfos|listcrls|listall [--utc]\n");
 	fprintf(out, "  Show list of supported algorithms:\n");
 	fprintf(out, "    stroke listalgs\n");
 	fprintf(out, "  Reload authority and attribute certificates:\n");
@@ -478,6 +478,7 @@ int main(int argc, char *argv[])
 {
 	const stroke_token_t *token;
 	char *cmd;
+	bool utc = FALSE;
 	int res = 0;
 
 	library_init(NULL, "stroke");
@@ -487,6 +488,7 @@ int main(int argc, char *argv[])
 	{
 		struct option long_opts[] = {
 			{"help",		no_argument,		NULL,	'h' },
+			{"utc",			no_argument,		NULL,	'u' },
 			{"daemon",		required_argument,	NULL,	'd' },
 			{0,0,0,0},
 		};
@@ -499,6 +501,9 @@ int main(int argc, char *argv[])
 			case 'd':
 				daemon_name = optarg;
 				continue;
+			case 'u':
+				utc = TRUE;
+				continue;
 			default:
 				return usage("invalid option");
 		}
@@ -611,7 +616,7 @@ int main(int argc, char *argv[])
 		case STROKE_LIST_ALGS:
 		case STROKE_LIST_PLUGINS:
 		case STROKE_LIST_ALL:
-			res = list(token->kw, argc && streq(argv[0], "--utc"));
+			res = list(token->kw, utc);
 			break;
 		case STROKE_REREAD_SECRETS:
 		case STROKE_REREAD_CACERTS:
diff --git a/src/swanctl/Makefile.am b/src/swanctl/Makefile.am
index 703e574..fb02714 100644
--- a/src/swanctl/Makefile.am
+++ b/src/swanctl/Makefile.am
@@ -4,6 +4,7 @@ swanctl_SOURCES = \
 	command.c command.h \
 	commands/initiate.c \
 	commands/terminate.c \
+	commands/redirect.c \
 	commands/install.c \
 	commands/list_sas.c \
 	commands/list_pols.c \
@@ -11,6 +12,7 @@ swanctl_SOURCES = \
 	commands/list_conns.c \
 	commands/list_certs.c \
 	commands/list_pools.c \
+	commands/list_algs.c \
 	commands/load_all.c \
 	commands/load_authorities.h  commands/load_authorities.c \
 	commands/load_conns.c commands/load_conns.h \
@@ -24,7 +26,8 @@ swanctl_SOURCES = \
 
 swanctl_LDADD = \
 	$(top_builddir)/src/libcharon/plugins/vici/libvici.la \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(PTHREADLIB) $(DLLIB)
 
 swanctl.o :		$(top_builddir)/config.status
 
@@ -62,10 +65,13 @@ install-data-local: swanctl.conf
 	test -e "$(DESTDIR)$(swanctldir)/x509" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/x509" || true
 	test -e "$(DESTDIR)$(swanctldir)/x509ca" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/x509ca" || true
 	test -e "$(DESTDIR)$(swanctldir)/x509aa" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/x509aa" || true
+	test -e "$(DESTDIR)$(swanctldir)/x509ocsp" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/x509ocsp" || true
 	test -e "$(DESTDIR)$(swanctldir)/x509crl" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/x509crl" || true
 	test -e "$(DESTDIR)$(swanctldir)/x509ac" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/x509ac" || true
+	test -e "$(DESTDIR)$(swanctldir)/pubkey" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/pubkey" || true
 	test -e "$(DESTDIR)$(swanctldir)/rsa" || $(INSTALL) -d -m 750 "$(DESTDIR)$(swanctldir)/rsa" || true
 	test -e "$(DESTDIR)$(swanctldir)/ecdsa" || $(INSTALL) -d -m 750 "$(DESTDIR)$(swanctldir)/ecdsa" || true
+	test -e "$(DESTDIR)$(swanctldir)/bliss" || $(INSTALL) -d -m 750 "$(DESTDIR)$(swanctldir)/bliss" || true
 	test -e "$(DESTDIR)$(swanctldir)/pkcs8" || $(INSTALL) -d -m 750 "$(DESTDIR)$(swanctldir)/pkcs8" || true
 	test -e "$(DESTDIR)$(swanctldir)/pkcs12" || $(INSTALL) -d -m 750 "$(DESTDIR)$(swanctldir)/pkcs12" || true
 	test -e "$(DESTDIR)$(swanctldir)/swanctl.conf" || $(INSTALL) -m 640 $(srcdir)/swanctl.conf $(DESTDIR)$(swanctldir)/swanctl.conf || true
diff --git a/src/swanctl/Makefile.in b/src/swanctl/Makefile.in
index a4d853c..94921af 100644
--- a/src/swanctl/Makefile.in
+++ b/src/swanctl/Makefile.in
@@ -105,20 +105,24 @@ am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man5dir)" \
 PROGRAMS = $(sbin_PROGRAMS)
 am__dirstamp = $(am__leading_dot)dirstamp
 am_swanctl_OBJECTS = command.$(OBJEXT) commands/initiate.$(OBJEXT) \
-	commands/terminate.$(OBJEXT) commands/install.$(OBJEXT) \
-	commands/list_sas.$(OBJEXT) commands/list_pols.$(OBJEXT) \
+	commands/terminate.$(OBJEXT) commands/redirect.$(OBJEXT) \
+	commands/install.$(OBJEXT) commands/list_sas.$(OBJEXT) \
+	commands/list_pols.$(OBJEXT) \
 	commands/list_authorities.$(OBJEXT) \
 	commands/list_conns.$(OBJEXT) commands/list_certs.$(OBJEXT) \
-	commands/list_pools.$(OBJEXT) commands/load_all.$(OBJEXT) \
+	commands/list_pools.$(OBJEXT) commands/list_algs.$(OBJEXT) \
+	commands/load_all.$(OBJEXT) \
 	commands/load_authorities.$(OBJEXT) \
 	commands/load_conns.$(OBJEXT) commands/load_creds.$(OBJEXT) \
 	commands/load_pools.$(OBJEXT) commands/log.$(OBJEXT) \
 	commands/version.$(OBJEXT) commands/stats.$(OBJEXT) \
 	commands/reload_settings.$(OBJEXT) swanctl.$(OBJEXT)
 swanctl_OBJECTS = $(am_swanctl_OBJECTS)
+am__DEPENDENCIES_1 =
 swanctl_DEPENDENCIES =  \
 	$(top_builddir)/src/libcharon/plugins/vici/libvici.la \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 AM_V_lt = $(am__v_lt_ at AM_V@)
 am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
 am__v_lt_0 = --silent
@@ -427,6 +431,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
@@ -444,6 +450,7 @@ swanctl_SOURCES = \
 	command.c command.h \
 	commands/initiate.c \
 	commands/terminate.c \
+	commands/redirect.c \
 	commands/install.c \
 	commands/list_sas.c \
 	commands/list_pols.c \
@@ -451,6 +458,7 @@ swanctl_SOURCES = \
 	commands/list_conns.c \
 	commands/list_certs.c \
 	commands/list_pools.c \
+	commands/list_algs.c \
 	commands/load_all.c \
 	commands/load_authorities.h  commands/load_authorities.c \
 	commands/load_conns.c commands/load_conns.h \
@@ -464,7 +472,8 @@ swanctl_SOURCES = \
 
 swanctl_LDADD = \
 	$(top_builddir)/src/libcharon/plugins/vici/libvici.la \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(PTHREADLIB) $(DLLIB)
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
@@ -579,6 +588,8 @@ commands/initiate.$(OBJEXT): commands/$(am__dirstamp) \
 	commands/$(DEPDIR)/$(am__dirstamp)
 commands/terminate.$(OBJEXT): commands/$(am__dirstamp) \
 	commands/$(DEPDIR)/$(am__dirstamp)
+commands/redirect.$(OBJEXT): commands/$(am__dirstamp) \
+	commands/$(DEPDIR)/$(am__dirstamp)
 commands/install.$(OBJEXT): commands/$(am__dirstamp) \
 	commands/$(DEPDIR)/$(am__dirstamp)
 commands/list_sas.$(OBJEXT): commands/$(am__dirstamp) \
@@ -593,6 +604,8 @@ commands/list_certs.$(OBJEXT): commands/$(am__dirstamp) \
 	commands/$(DEPDIR)/$(am__dirstamp)
 commands/list_pools.$(OBJEXT): commands/$(am__dirstamp) \
 	commands/$(DEPDIR)/$(am__dirstamp)
+commands/list_algs.$(OBJEXT): commands/$(am__dirstamp) \
+	commands/$(DEPDIR)/$(am__dirstamp)
 commands/load_all.$(OBJEXT): commands/$(am__dirstamp) \
 	commands/$(DEPDIR)/$(am__dirstamp)
 commands/load_authorities.$(OBJEXT): commands/$(am__dirstamp) \
@@ -627,6 +640,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/swanctl.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/initiate.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/install.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/list_algs.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/list_authorities.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/list_certs.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/list_conns.Po at am__quote@
@@ -639,6 +653,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/load_creds.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/load_pools.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/log.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/redirect.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/reload_settings.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/stats.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/terminate.Po at am__quote@
@@ -1001,10 +1016,13 @@ install-data-local: swanctl.conf
 	test -e "$(DESTDIR)$(swanctldir)/x509" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/x509" || true
 	test -e "$(DESTDIR)$(swanctldir)/x509ca" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/x509ca" || true
 	test -e "$(DESTDIR)$(swanctldir)/x509aa" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/x509aa" || true
+	test -e "$(DESTDIR)$(swanctldir)/x509ocsp" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/x509ocsp" || true
 	test -e "$(DESTDIR)$(swanctldir)/x509crl" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/x509crl" || true
 	test -e "$(DESTDIR)$(swanctldir)/x509ac" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/x509ac" || true
+	test -e "$(DESTDIR)$(swanctldir)/pubkey" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/pubkey" || true
 	test -e "$(DESTDIR)$(swanctldir)/rsa" || $(INSTALL) -d -m 750 "$(DESTDIR)$(swanctldir)/rsa" || true
 	test -e "$(DESTDIR)$(swanctldir)/ecdsa" || $(INSTALL) -d -m 750 "$(DESTDIR)$(swanctldir)/ecdsa" || true
+	test -e "$(DESTDIR)$(swanctldir)/bliss" || $(INSTALL) -d -m 750 "$(DESTDIR)$(swanctldir)/bliss" || true
 	test -e "$(DESTDIR)$(swanctldir)/pkcs8" || $(INSTALL) -d -m 750 "$(DESTDIR)$(swanctldir)/pkcs8" || true
 	test -e "$(DESTDIR)$(swanctldir)/pkcs12" || $(INSTALL) -d -m 750 "$(DESTDIR)$(swanctldir)/pkcs12" || true
 	test -e "$(DESTDIR)$(swanctldir)/swanctl.conf" || $(INSTALL) -m 640 $(srcdir)/swanctl.conf $(DESTDIR)$(swanctldir)/swanctl.conf || true
diff --git a/src/swanctl/command.c b/src/swanctl/command.c
index 26c4134..fd9bc00 100644
--- a/src/swanctl/command.c
+++ b/src/swanctl/command.c
@@ -176,6 +176,15 @@ void command_register(command_t command)
 				"uri",		'u', 1, "service URI to connect to"
 			};
 		}
+		for (i = 0; cmds[registered].line[i]; i++)
+		{
+			if (i == MAX_LINES - 1)
+			{
+				fprintf(stderr, "command '%s' specifies too many usage summary "
+						"lines, please increase MAX_LINES\n", command.cmd);
+				break;
+			}
+		}
 	}
 	registered++;
 }
@@ -217,7 +226,7 @@ int command_usage(char *error, ...)
 	}
 	else
 	{
-		for (i = 0; cmds[active].line[i]; i++)
+		for (i = 0; i < MAX_LINES && cmds[active].line[i]; i++)
 		{
 			if (i == 0)
 			{
diff --git a/src/swanctl/command.h b/src/swanctl/command.h
index 0760d13..8d0a2e6 100644
--- a/src/swanctl/command.h
+++ b/src/swanctl/command.h
@@ -27,12 +27,12 @@
 /**
  * Maximum number of commands (+1).
  */
-#define MAX_COMMANDS 21
+#define MAX_COMMANDS 23
 
 /**
  * Maximum number of options in a command (+3)
  */
-#define MAX_OPTIONS 32
+#define MAX_OPTIONS 34
 
 /**
  * Maximum number of usage summary lines (+1)
diff --git a/src/swanctl/commands/list_algs.c b/src/swanctl/commands/list_algs.c
new file mode 100644
index 0000000..616e6ff
--- /dev/null
+++ b/src/swanctl/commands/list_algs.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "command.h"
+
+#include <errno.h>
+
+CALLBACK(algs, int,
+	void *null, vici_res_t *res, char *name, void *value, int len)
+{
+	if (chunk_printable(chunk_create(value, len), NULL, ' '))
+	{
+		printf("  %s[%.*s]\n", name, len, value);
+	}
+	return 0;
+}
+
+CALLBACK(types, int,
+	void *null, vici_res_t *res, char *name)
+{
+	printf("%s:\n", name);
+	return vici_parse_cb(res, NULL, algs, NULL, NULL);
+}
+
+static int algorithms(vici_conn_t *conn)
+{
+	vici_req_t *req;
+	vici_res_t *res;
+	char *arg;
+	command_format_options_t format = COMMAND_FORMAT_NONE;
+	int ret;
+
+	while (TRUE)
+	{
+		switch (command_getopt(&arg))
+		{
+			case 'h':
+				return command_usage(NULL);
+			case 'P':
+				format |= COMMAND_FORMAT_PRETTY;
+				/* fall through to raw */
+			case 'r':
+				format |= COMMAND_FORMAT_RAW;
+				continue;
+			case EOF:
+				break;
+			default:
+				return command_usage("invalid --list-algs option");
+		}
+		break;
+	}
+
+	req = vici_begin("get-algorithms");
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		ret = errno;
+		fprintf(stderr, "get-algorithms request failed: %s\n", strerror(errno));
+		return ret;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "get-algorithms reply", format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	else
+	{
+		if (vici_parse_cb(res, types, NULL, NULL, NULL) != 0)
+		{
+			fprintf(stderr, "parsing get-algorithms reply failed: %s\n",
+					strerror(errno));
+		}
+	}
+	vici_free_res(res);
+	return 0;
+}
+
+/**
+ * Register the command.
+ */
+static void __attribute__ ((constructor))reg()
+{
+	command_register((command_t) {
+		algorithms, 'g', "list-algs", "show loaded algorithms",
+		{"[--raw|--pretty]"},
+		{
+			{"help",		'h', 0, "show usage information"},
+			{"raw",			'r', 0, "dump raw response message"},
+			{"pretty",		'P', 0, "dump raw response message in pretty print"},
+		}
+	});
+}
diff --git a/src/swanctl/commands/list_certs.c b/src/swanctl/commands/list_certs.c
index 167f8d8..e9c9647 100644
--- a/src/swanctl/commands/list_certs.c
+++ b/src/swanctl/commands/list_certs.c
@@ -24,14 +24,17 @@
 #include <asn1/asn1.h>
 #include <asn1/oid.h>
 #include <credentials/certificates/certificate.h>
-#include <credentials/certificates/x509.h>
-#include <credentials/certificates/crl.h>
-#include <credentials/certificates/ac.h>
+#include <credentials/certificates/certificate_printer.h>
 #include <selectors/traffic_selector.h>
 
 #include "command.h"
 
 /**
+ * Static certificate printer object
+ */
+static certificate_printer_t *cert_printer = NULL;
+
+/**
  * Print PEM encoding of a certificate
  */
 static void print_pem(certificate_t *cert)
@@ -49,541 +52,99 @@ static void print_pem(certificate_t *cert)
 	}
 }
 
-/**
- * Print public key information
- */
-static void print_pubkey(public_key_t *key, bool has_privkey)
-{
-	chunk_t chunk;
-
-	printf("pubkey:    %N %d bits", key_type_names, key->get_type(key),
-		   key->get_keysize(key));
-	if (has_privkey)
-	{
-		printf(", has private key");
-	}
-	printf("\n");
-	if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &chunk))
-	{
-		printf("keyid:     %#B\n", &chunk);
-	}
-	if (key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &chunk))
-	{
-		printf("subjkey:   %#B\n", &chunk);
-	}
-}
-
-/**
- * Print X509 specific certificate information
- */
-static void print_x509(x509_t *x509)
+CALLBACK(list_cb, void,
+	command_format_options_t *format, char *name, vici_res_t *res)
 {
-	enumerator_t *enumerator;
-	identification_t *id;
-	traffic_selector_t *block;
-	chunk_t chunk;
-	bool first;
-	char *uri;
-	int len, explicit, inhibit;
-	x509_flag_t flags;
-	x509_cdp_t *cdp;
-	x509_cert_policy_t *policy;
-	x509_policy_mapping_t *mapping;
-
-	chunk = chunk_skip_zero(x509->get_serial(x509));
-	printf("serial:    %#B\n", &chunk);
-
-	first = TRUE;
-	enumerator = x509->create_subjectAltName_enumerator(x509);
-	while (enumerator->enumerate(enumerator, &id))
-	{
-		if (first)
-		{
-			printf("altNames:  ");
-			first = FALSE;
-		}
-		else
-		{
-			printf(", ");
-		}
-		printf("%Y", id);
-	}
-	if (!first)
-	{
-		printf("\n");
-	}
-	enumerator->destroy(enumerator);
-
-	flags = x509->get_flags(x509);
-	printf("flags:     ");
-	if (flags & X509_CA)
-	{
-		printf("CA ");
-	}
-	if (flags & X509_CRL_SIGN)
-	{
-		printf("CRLSign ");
-	}
-	if (flags & X509_AA)
-	{
-		printf("AA ");
-	}
-	if (flags & X509_OCSP_SIGNER)
-	{
-		printf("OCSP ");
-	}
-	if (flags & X509_AA)
-	{
-		printf("AA ");
-	}
-	if (flags & X509_SERVER_AUTH)
-	{
-		printf("serverAuth ");
-	}
-	if (flags & X509_CLIENT_AUTH)
-	{
-		printf("clientAuth ");
-	}
-	if (flags & X509_IKE_INTERMEDIATE)
-	{
-		printf("iKEIntermediate ");
-	}
-	if (flags & X509_SELF_SIGNED)
-	{
-		printf("self-signed ");
-	}
-	printf("\n");
-
-	first = TRUE;
-	enumerator = x509->create_crl_uri_enumerator(x509);
-	while (enumerator->enumerate(enumerator, &cdp))
-	{
-		if (first)
-		{
-			printf("CRL URIs:  %s", cdp->uri);
-			first = FALSE;
-		}
-		else
-		{
-			printf("           %s", cdp->uri);
-		}
-		if (cdp->issuer)
-		{
-			printf(" (CRL issuer: %Y)", cdp->issuer);
-		}
-		printf("\n");
-	}
-	enumerator->destroy(enumerator);
-
-	first = TRUE;
-	enumerator = x509->create_ocsp_uri_enumerator(x509);
-	while (enumerator->enumerate(enumerator, &uri))
-	{
-		if (first)
-		{
-			printf("OCSP URIs: %s\n", uri);
-			first = FALSE;
-		}
-		else
-		{
-			printf("           %s\n", uri);
-		}
-	}
-	enumerator->destroy(enumerator);
-
-	len = x509->get_constraint(x509, X509_PATH_LEN);
-	if (len != X509_NO_CONSTRAINT)
-	{
-		printf("pathlen:   %d\n", len);
-	}
-
-	first = TRUE;
-	enumerator = x509->create_name_constraint_enumerator(x509, TRUE);
-	while (enumerator->enumerate(enumerator, &id))
-	{
-		if (first)
-		{
-			printf("Permitted NameConstraints:\n");
-			first = FALSE;
-		}
-		printf("           %Y\n", id);
-	}
-	enumerator->destroy(enumerator);
-	first = TRUE;
-	enumerator = x509->create_name_constraint_enumerator(x509, FALSE);
-	while (enumerator->enumerate(enumerator, &id))
-	{
-		if (first)
-		{
-			printf("Excluded NameConstraints:\n");
-			first = FALSE;
-		}
-		printf("           %Y\n", id);
-	}
-	enumerator->destroy(enumerator);
-
-	first = TRUE;
-	enumerator = x509->create_cert_policy_enumerator(x509);
-	while (enumerator->enumerate(enumerator, &policy))
-	{
-		char *oid;
-
-		if (first)
-		{
-			printf("CertificatePolicies:\n");
-			first = FALSE;
-		}
-		oid = asn1_oid_to_string(policy->oid);
-		if (oid)
-		{
-			printf("           %s\n", oid);
-			free(oid);
-		}
-		else
-		{
-			printf("           %#B\n", &policy->oid);
-		}
-		if (policy->cps_uri)
-		{
-			printf("             CPS: %s\n", policy->cps_uri);
-		}
-		if (policy->unotice_text)
-		{
-			printf("             Notice: %s\n", policy->unotice_text);
-
-		}
-	}
-	enumerator->destroy(enumerator);
-
-	first = TRUE;
-	enumerator = x509->create_policy_mapping_enumerator(x509);
-	while (enumerator->enumerate(enumerator, &mapping))
-	{
-		char *issuer_oid, *subject_oid;
-
-		if (first)
-		{
-			printf("PolicyMappings:\n");
-			first = FALSE;
-		}
-		issuer_oid = asn1_oid_to_string(mapping->issuer);
-		subject_oid = asn1_oid_to_string(mapping->subject);
-		printf("           %s => %s\n", issuer_oid, subject_oid);
-		free(issuer_oid);
-		free(subject_oid);
-	}
-	enumerator->destroy(enumerator);
-
-	explicit = x509->get_constraint(x509, X509_REQUIRE_EXPLICIT_POLICY);
-	inhibit = x509->get_constraint(x509, X509_INHIBIT_POLICY_MAPPING);
-	len = x509->get_constraint(x509, X509_INHIBIT_ANY_POLICY);
+	certificate_t *cert;
+	certificate_type_t type;
+	x509_flag_t flag = X509_NONE;
+	identification_t *subject = NULL;
+	time_t not_before = UNDEFINED_TIME;
+	time_t not_after  = UNDEFINED_TIME;
+	chunk_t t_ch;
+	bool has_privkey;
+	char *str;
+	void *buf;
+	int len;
 
-	if (explicit != X509_NO_CONSTRAINT || inhibit != X509_NO_CONSTRAINT ||
-		len != X509_NO_CONSTRAINT)
+	if (*format & COMMAND_FORMAT_RAW)
 	{
-		printf("PolicyConstraints:\n");
-		if (explicit != X509_NO_CONSTRAINT)
-		{
-			printf("           requireExplicitPolicy: %d\n", explicit);
-		}
-		if (inhibit != X509_NO_CONSTRAINT)
-		{
-			printf("           inhibitPolicyMapping: %d\n", inhibit);
-		}
-		if (len != X509_NO_CONSTRAINT)
-		{
-			printf("           inhibitAnyPolicy: %d\n", len);
-		}
+		vici_dump(res, "list-cert event", *format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+		return;
 	}
 
-	chunk = x509->get_authKeyIdentifier(x509);
-	if (chunk.ptr)
+	buf = vici_find(res, &len, "data");
+	if (!buf)
 	{
-		printf("authkeyId: %#B\n", &chunk);
+		fprintf(stderr, "received incomplete certificate data\n");
+		return;
 	}
+	has_privkey = streq(vici_find_str(res, "no", "has_privkey"), "yes");
 
-	chunk = x509->get_subjectKeyIdentifier(x509);
-	if (chunk.ptr)
+	str = vici_find_str(res, "ANY", "type");
+	if (!enum_from_name(certificate_type_names, str, &type) || type == CERT_ANY)
 	{
-		printf("subjkeyId: %#B\n", &chunk);
+		fprintf(stderr, "unsupported certificate type '%s'\n", str);
+		return;
 	}
-	if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
+	if (type == CERT_X509)
 	{
-		first = TRUE;
-		printf("addresses: ");
-		enumerator = x509->create_ipAddrBlock_enumerator(x509);
-		while (enumerator->enumerate(enumerator, &block))
+		str = vici_find_str(res, "ANY", "flag");
+		if (!enum_from_name(x509_flag_names, str, &flag) || flag == X509_ANY)
 		{
-			if (first)
-			{
-				first = FALSE;
-			}
-			else
-			{
-				printf(", ");
-			}
-			printf("%R", block);
+			fprintf(stderr, "unsupported certificate flag '%s'\n", str);
+			return;
 		}
-		enumerator->destroy(enumerator);
-		printf("\n");
 	}
-}
-
-/**
- * Print CRL specific information
- */
-static void print_crl(crl_t *crl)
-{
-	enumerator_t *enumerator;
-	time_t ts;
-	crl_reason_t reason;
-	chunk_t chunk;
-	int count = 0;
-	bool first;
-	char buf[64];
-	struct tm tm;
-	x509_cdp_t *cdp;
-
-	chunk = chunk_skip_zero(crl->get_serial(crl));
-	printf("serial:    %#B\n", &chunk);
-
-	if (crl->is_delta_crl(crl, &chunk))
-	{
-		chunk = chunk_skip_zero(chunk);
-		printf("delta CRL: for serial %#B\n", &chunk);
-	}
-	chunk = crl->get_authKeyIdentifier(crl);
-	printf("authKeyId: %#B\n", &chunk);
-
-	first = TRUE;
-	enumerator = crl->create_delta_crl_uri_enumerator(crl);
-	while (enumerator->enumerate(enumerator, &cdp))
+	if (type == CERT_TRUSTED_PUBKEY)
 	{
-		if (first)
+		str = vici_find_str(res, NULL, "subject");
+		if (str)
 		{
-			printf("freshest:  %s", cdp->uri);
-			first = FALSE;
+			subject = identification_create_from_string(str);
 		}
-		else
+		str = vici_find_str(res, NULL, "not-before");
+		if (str)
 		{
-			printf("           %s", cdp->uri);
+			t_ch = chunk_from_str(str);
+			not_before = asn1_to_time(&t_ch, ASN1_GENERALIZEDTIME);
 		}
-		if (cdp->issuer)
+		str = vici_find_str(res, NULL, "not-after");
+		if (str)
 		{
-			printf(" (CRL issuer: %Y)", cdp->issuer);
+			t_ch = chunk_from_str(str);
+			not_after = asn1_to_time(&t_ch, ASN1_GENERALIZEDTIME);
 		}
-		printf("\n");
+		cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
+								  BUILD_BLOB_ASN1_DER, chunk_create(buf, len),
+								  BUILD_NOT_BEFORE_TIME, not_before,
+								  BUILD_NOT_AFTER_TIME, not_after,
+								  BUILD_SUBJECT, subject, BUILD_END);
+		DESTROY_IF(subject);
 	}
-	enumerator->destroy(enumerator);
-
-	enumerator = crl->create_enumerator(crl);
-	while (enumerator->enumerate(enumerator, &chunk, &ts, &reason))
-	{
-		count++;
-	}
-	enumerator->destroy(enumerator);
-
-	printf("%d revoked certificate%s%s\n", count,
-		   count == 1 ? "" : "s", count ? ":" : "");
-	enumerator = crl->create_enumerator(crl);
-	while (enumerator->enumerate(enumerator, &chunk, &ts, &reason))
-	{
-		chunk = chunk_skip_zero(chunk);
-		localtime_r(&ts, &tm);
-		strftime(buf, sizeof(buf), "%F %T", &tm);
-		printf("    %#B: %s, %N\n", &chunk, buf, crl_reason_names, reason);
-		count++;
-	}
-	enumerator->destroy(enumerator);
-}
-
-/**
- * Print AC specific information
- */
-static void print_ac(ac_t *ac)
-{
-	ac_group_type_t type;
-	identification_t *id;
-	enumerator_t *groups;
-	chunk_t chunk;
-	bool first = TRUE;
-
-	chunk = chunk_skip_zero(ac->get_serial(ac));
-	printf("serial:    %#B\n", &chunk);
-
-	id = ac->get_holderIssuer(ac);
-	if (id)
-	{
-		printf("hissuer:  \"%Y\"\n", id);
-	}
-	chunk = chunk_skip_zero(ac->get_holderSerial(ac));
-	if (chunk.ptr)
+	else
 	{
-		printf("hserial:   %#B\n", &chunk);
+		cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
+								  BUILD_BLOB_ASN1_DER, chunk_create(buf, len),
+								  BUILD_END);
 	}
-	groups = ac->create_group_enumerator(ac);
-	while (groups->enumerate(groups, &type, &chunk))
+	if (cert)
 	{
-		int oid;
-		char *str;
-
-		if (first)
+		if (*format & COMMAND_FORMAT_PEM)
 		{
-			printf("groups:    ");
-			first = FALSE;
+			print_pem(cert);
 		}
 		else
 		{
-			printf("           ");
-		}
-		switch (type)
-		{
-			case AC_GROUP_TYPE_STRING:
-				printf("%.*s", (int)chunk.len, chunk.ptr);
-				break;
-			case AC_GROUP_TYPE_OID:
-				oid = asn1_known_oid(chunk);
-				if (oid == OID_UNKNOWN)
-				{
-					str = asn1_oid_to_string(chunk);
-					if (str)
-					{
-						printf("%s", str);
-						free(str);
-					}
-					else
-					{
-						printf("OID:%#B", &chunk);
-					}
-				}
-				else
-				{
-					printf("%s", oid_names[oid].name);
-				}
-				break;
-			case AC_GROUP_TYPE_OCTETS:
-				printf("%#B", &chunk);
-				break;
+			cert_printer->print_caption(cert_printer, type, flag);
+			cert_printer->print(cert_printer, cert, has_privkey);
 		}
-		printf("\n");
-	}
-	groups->destroy(groups);
-
-	chunk = ac->get_authKeyIdentifier(ac);
-	if (chunk.ptr)
-	{
-		printf("authkey:  %#B\n", &chunk);
-	}
-}
-
-/**
- * Print certificate information
- */
-static void print_cert(certificate_t *cert, bool has_privkey)
-{
-	time_t now, notAfter, notBefore;
-	public_key_t *key;
-
-	now = time(NULL);
-
-	printf("cert:      %N\n", certificate_type_names, cert->get_type(cert));
-	if (cert->get_type(cert) != CERT_X509_CRL)
-	{
-		printf("subject:  \"%Y\"\n", cert->get_subject(cert));
-	}
-	printf("issuer:   \"%Y\"\n", cert->get_issuer(cert));
-
-	cert->get_validity(cert, &now, &notBefore, &notAfter);
-	printf("validity:  not before %T, ", &notBefore, FALSE);
-	if (now < notBefore)
-	{
-		printf("not valid yet (valid in %V)\n", &now, &notBefore);
+		cert->destroy(cert);
 	}
 	else
 	{
-		printf("ok\n");
-	}
-	printf("           not after  %T, ", &notAfter, FALSE);
-	if (now > notAfter)
-	{
-		printf("expired (%V ago)\n", &now, &notAfter);
-	}
-	else
-	{
-		printf("ok (expires in %V)\n", &now, &notAfter);
-	}
-
-	switch (cert->get_type(cert))
-	{
-		case CERT_X509:
-			print_x509((x509_t*)cert);
-			break;
-		case CERT_X509_CRL:
-			print_crl((crl_t*)cert);
-			break;
-		case CERT_X509_AC:
-			print_ac((ac_t*)cert);
-			break;
-		default:
-			fprintf(stderr, "parsing certificate subtype %N not implemented\n",
-					certificate_type_names, cert->get_type(cert));
-			break;
-	}
-	key = cert->get_public_key(cert);
-	if (key)
-	{
-		print_pubkey(key, has_privkey);
-		key->destroy(key);
-	}
-	printf("\n");
-}
-
-CALLBACK(list_cb, void,
-	command_format_options_t *format, char *name, vici_res_t *res)
-{
-	if (*format & COMMAND_FORMAT_RAW)
-	{
-		vici_dump(res, "list-cert event", *format & COMMAND_FORMAT_PRETTY,
-				  stdout);
-	}
-	else
-	{
-		certificate_type_t type;
-		certificate_t *cert;
-		void *buf;
-		int len;
-		bool has_privkey;
-
-		buf = vici_find(res, &len, "data");
-		has_privkey = streq(vici_find_str(res, "no", "has_privkey"), "yes");
-		if (enum_from_name(certificate_type_names,
-						   vici_find_str(res, "ANY", "type"), &type) &&
-			type != CERT_ANY && buf)
-		{
-			cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
-									BUILD_BLOB_ASN1_DER, chunk_create(buf, len),
-									BUILD_END);
-			if (cert)
-			{
-				if (*format & COMMAND_FORMAT_PEM)
-				{
-					print_pem(cert);
-				}
-				else
-				{
-					print_cert(cert, has_privkey);
-				}
-				cert->destroy(cert);
-			}
-			else
-			{
-				fprintf(stderr, "parsing certificate failed\n");
-			}
-		}
-		else
-		{
-			fprintf(stderr, "received incomplete certificate data\n");
-		}
+		fprintf(stderr, "parsing certificate failed\n");
 	}
 }
 
@@ -592,7 +153,8 @@ static int list_certs(vici_conn_t *conn)
 	vici_req_t *req;
 	vici_res_t *res;
 	command_format_options_t format = COMMAND_FORMAT_NONE;
-	char *arg, *subject = NULL, *type = NULL;
+	char *arg, *subject = NULL, *type = NULL, *flag = NULL;
+	bool detailed = TRUE, utc = FALSE;
 	int ret;
 
 	while (TRUE)
@@ -607,6 +169,9 @@ static int list_certs(vici_conn_t *conn)
 			case 't':
 				type = arg;
 				continue;
+			case 'f':
+				flag = arg;
+				continue;
 			case 'p':
 				format |= COMMAND_FORMAT_PEM;
 				continue;
@@ -616,6 +181,12 @@ static int list_certs(vici_conn_t *conn)
 			case 'r':
 				format |= COMMAND_FORMAT_RAW;
 				continue;
+			case 'S':
+				detailed = FALSE;
+				continue;
+			case 'U':
+				utc = TRUE;
+				continue;
 			case EOF:
 				break;
 			default:
@@ -631,19 +202,28 @@ static int list_certs(vici_conn_t *conn)
 		return ret;
 	}
 	req = vici_begin("list-certs");
+
 	if (type)
 	{
 		vici_add_key_valuef(req, "type", "%s", type);
 	}
+	if (flag)
+	{
+		vici_add_key_valuef(req, "flag", "%s", flag);
+	}
 	if (subject)
 	{
 		vici_add_key_valuef(req, "subject", "%s", subject);
 	}
+	cert_printer = certificate_printer_create(stdout, detailed, utc);
+
 	res = vici_submit(req, conn);
 	if (!res)
 	{
 		ret = errno;
 		fprintf(stderr, "list-certs request failed: %s\n", strerror(errno));
+		cert_printer->destroy(cert_printer);
+		cert_printer = NULL;
 		return ret;
 	}
 	if (format & COMMAND_FORMAT_RAW)
@@ -652,6 +232,9 @@ static int list_certs(vici_conn_t *conn)
 				  stdout);
 	}
 	vici_free_res(res);
+
+	cert_printer->destroy(cert_printer);
+	cert_printer = NULL;
 	return 0;
 }
 
@@ -662,15 +245,19 @@ static void __attribute__ ((constructor))reg()
 {
 	command_register((command_t) {
 		list_certs, 'x', "list-certs", "list stored certificates",
-		{"[--subject <dn/san>] [--type X509|X509_AC|X509_CRL] [--pem] "
-		 "[--raw|--pretty]"},
+		{"[--subject <dn/san>] [--pem]",
+		 "[--type x509|x509_ac|x509_crl|ocsp_response|pubkey]",
+		 "[--flag none|ca|aa|ocsp|any] [--raw|--pretty|--short|--utc]"},
 		{
 			{"help",		'h', 0, "show usage information"},
 			{"subject",		's', 1, "filter by certificate subject"},
 			{"type",		't', 1, "filter by certificate type"},
+			{"flag",		'f', 1, "filter by X.509 certificate flag"},
 			{"pem",			'p', 0, "print PEM encoding of certificate"},
 			{"raw",			'r', 0, "dump raw response message"},
 			{"pretty",		'P', 0, "dump raw response message in pretty print"},
+			{"short",		'S', 0, "omit some certificate details"},
+			{"utc",			'U', 0, "use UTC for time fields"},
 		}
 	});
 }
diff --git a/src/swanctl/commands/list_sas.c b/src/swanctl/commands/list_sas.c
index 93dd7ed..fd08022 100644
--- a/src/swanctl/commands/list_sas.c
+++ b/src/swanctl/commands/list_sas.c
@@ -2,6 +2,9 @@
  * Copyright (C) 2014 Martin Willi
  * Copyright (C) 2014 revosec AG
  *
+ * Copyright (C) 2016 Andreas Steffen
+ * HSR 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
@@ -198,16 +201,18 @@ CALLBACK(ike_sa, int,
 			ike->get(ike, "state"), ike->get(ike, "version"),
 			ike->get(ike, "initiator-spi"), ike->get(ike, "responder-spi"));
 
-		printf("  local  '%s' @ %s",
-			ike->get(ike, "local-id"), ike->get(ike, "local-host"));
+		printf("  local  '%s' @ %s[%s]",
+			ike->get(ike, "local-id"), ike->get(ike, "local-host"),
+			ike->get(ike, "local-port"));
 		if (ike->get(ike, "local-vips"))
 		{
 			printf(" [%s]", ike->get(ike, "local-vips"));
 		}
 		printf("\n");
 
-		printf("  remote '%s' @ %s",
-			ike->get(ike, "remote-id"), ike->get(ike, "remote-host"));
+		printf("  remote '%s' @ %s[%s]",
+			ike->get(ike, "remote-id"), ike->get(ike, "remote-host"),
+			ike->get(ike, "remote-port"));
 		if (ike->get(ike, "remote-eap-id"))
 		{
 			printf(" EAP: '%s'", ike->get(ike, "remote-eap-id"));
diff --git a/src/swanctl/commands/load_conns.c b/src/swanctl/commands/load_conns.c
index 6ee8b87..bbc700d 100644
--- a/src/swanctl/commands/load_conns.c
+++ b/src/swanctl/commands/load_conns.c
@@ -59,6 +59,7 @@ static bool is_file_list_key(char *key)
 	char *keys[] = {
 		"certs",
 		"cacerts",
+		"pubkeys"
 	};
 	int i;
 
@@ -112,12 +113,18 @@ static bool add_file_list_key(vici_req_t *req, char *key, char *value)
 						 SWANCTL_X509DIR, DIRECTORY_SEPARATOR, token);
 				token = buf;
 			}
-			if (streq(key, "cacerts"))
+			else if (streq(key, "cacerts"))
 			{
 				snprintf(buf, sizeof(buf), "%s%s%s",
 						 SWANCTL_X509CADIR, DIRECTORY_SEPARATOR, token);
 				token = buf;
 			}
+			else if (streq(key, "pubkeys"))
+			{
+				snprintf(buf, sizeof(buf), "%s%s%s",
+						 SWANCTL_PUBKEYDIR, DIRECTORY_SEPARATOR, token);
+				token = buf;
+			}
 		}
 
 		map = chunk_map(token, FALSE);
diff --git a/src/swanctl/commands/load_creds.c b/src/swanctl/commands/load_creds.c
index d2ebc22..4647934 100644
--- a/src/swanctl/commands/load_creds.c
+++ b/src/swanctl/commands/load_creds.c
@@ -2,6 +2,9 @@
  * Copyright (C) 2014 Martin Willi
  * Copyright (C) 2014 revosec AG
  *
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR 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
@@ -27,11 +30,14 @@
 #include <credentials/sets/callback_cred.h>
 #include <credentials/containers/pkcs12.h>
 
+#include <vici_cert_info.h>
+
 /**
  * Load a single certificate over vici
  */
 static bool load_cert(vici_conn_t *conn, command_format_options_t format,
-					  char *dir, char *type, chunk_t data)
+					  char *dir, certificate_type_t type, x509_flag_t flag,
+					  chunk_t data)
 {
 	vici_req_t *req;
 	vici_res_t *res;
@@ -39,7 +45,11 @@ static bool load_cert(vici_conn_t *conn, command_format_options_t format,
 
 	req = vici_begin("load-cert");
 
-	vici_add_key_valuef(req, "type", "%s", type);
+	vici_add_key_valuef(req, "type", "%N", certificate_type_names, type);
+	if (type == CERT_X509)
+	{
+		vici_add_key_valuef(req, "flag", "%N", x509_flag_names, flag);
+	}
 	vici_add_key_value(req, "data", data.ptr, data.len);
 
 	res = vici_submit(req, conn);
@@ -61,7 +71,7 @@ static bool load_cert(vici_conn_t *conn, command_format_options_t format,
 	}
 	else
 	{
-		printf("loaded %s certificate from '%s'\n", type, dir);
+		printf("loaded certificate from '%s'\n", dir);
 	}
 	vici_free_res(res);
 	return ret;
@@ -71,13 +81,17 @@ static bool load_cert(vici_conn_t *conn, command_format_options_t format,
  * Load certficiates from a directory
  */
 static void load_certs(vici_conn_t *conn, command_format_options_t format,
-					   char *type, char *dir)
+					   char *type_str, char *dir)
 {
 	enumerator_t *enumerator;
+	certificate_type_t type;
+	x509_flag_t flag;
 	struct stat st;
 	chunk_t *map;
 	char *path;
 
+	vici_cert_info_from_str(type_str, &type, &flag);
+
 	enumerator = enumerator_create_directory(dir);
 	if (enumerator)
 	{
@@ -88,7 +102,7 @@ static void load_certs(vici_conn_t *conn, command_format_options_t format,
 				map = chunk_map(path, FALSE);
 				if (map)
 				{
-					load_cert(conn, format, path, type, *map);
+					load_cert(conn, format, path, type, flag, *map);
 					chunk_unmap(map);
 				}
 				else
@@ -171,6 +185,9 @@ static bool load_key_anytype(vici_conn_t *conn, command_format_options_t format,
 		case KEY_ECDSA:
 			loaded = load_key(conn, format, path, "ecdsa", encoding);
 			break;
+		case KEY_BLISS:
+			loaded = load_key(conn, format, path, "bliss", encoding);
+			break;
 		default:
 			fprintf(stderr, "unsupported key type in '%s'\n", path);
 			break;
@@ -237,6 +254,7 @@ static bool determine_credtype(char *type, credential_type_t *credtype,
 		{ "pkcs8",			CRED_PRIVATE_KEY,		KEY_ANY,			},
 		{ "rsa",			CRED_PRIVATE_KEY,		KEY_RSA,			},
 		{ "ecdsa",			CRED_PRIVATE_KEY,		KEY_ECDSA,			},
+		{ "bliss",			CRED_PRIVATE_KEY,		KEY_BLISS,			},
 		{ "pkcs12",			CRED_CONTAINER,			CONTAINER_PKCS12,	},
 	};
 	int i;
@@ -439,7 +457,8 @@ static bool load_pkcs12(vici_conn_t *conn, command_format_options_t format,
 		loaded = FALSE;
 		if (cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
 		{
-			loaded = load_cert(conn, format, path, "x509", encoding);
+			loaded = load_cert(conn, format, path, CERT_X509, X509_NONE,
+							   encoding);
 			if (loaded)
 			{
 				fprintf(stderr, "  %Y\n", cert->get_subject(cert));
@@ -548,6 +567,7 @@ static bool load_secret(vici_conn_t *conn, settings_t *cfg,
 		"ike",
 		"rsa",
 		"ecdsa",
+		"bliss",
 		"pkcs8",
 		"pkcs12",
 	};
@@ -672,14 +692,17 @@ int load_creds_cfg(vici_conn_t *conn, command_format_options_t format,
 		}
 	}
 
-	load_certs(conn, format, "x509", SWANCTL_X509DIR);
-	load_certs(conn, format, "x509ca", SWANCTL_X509CADIR);
-	load_certs(conn, format, "x509aa", SWANCTL_X509AADIR);
-	load_certs(conn, format, "x509crl", SWANCTL_X509CRLDIR);
-	load_certs(conn, format, "x509ac", SWANCTL_X509ACDIR);
+	load_certs(conn, format, "x509",     SWANCTL_X509DIR);
+	load_certs(conn, format, "x509ca",   SWANCTL_X509CADIR);
+	load_certs(conn, format, "x509ocsp", SWANCTL_X509OCSPDIR);
+	load_certs(conn, format, "x509aa",   SWANCTL_X509AADIR);
+	load_certs(conn, format, "x509ac",   SWANCTL_X509ACDIR);
+	load_certs(conn, format, "x509crl",  SWANCTL_X509CRLDIR);
+	load_certs(conn, format, "pubkey",   SWANCTL_PUBKEYDIR);
 
-	load_keys(conn, format, noprompt, cfg, "rsa", SWANCTL_RSADIR);
+	load_keys(conn, format, noprompt, cfg, "rsa",   SWANCTL_RSADIR);
 	load_keys(conn, format, noprompt, cfg, "ecdsa", SWANCTL_ECDSADIR);
+	load_keys(conn, format, noprompt, cfg, "bliss", SWANCTL_BLISSDIR);
 	load_keys(conn, format, noprompt, cfg, "pkcs8", SWANCTL_PKCS8DIR);
 
 	load_containers(conn, format, noprompt, cfg, "pkcs12", SWANCTL_PKCS12DIR);
diff --git a/src/swanctl/commands/redirect.c b/src/swanctl/commands/redirect.c
new file mode 100644
index 0000000..6edb936
--- /dev/null
+++ b/src/swanctl/commands/redirect.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "command.h"
+
+#include <errno.h>
+
+static int redirect(vici_conn_t *conn)
+{
+	vici_req_t *req;
+	vici_res_t *res;
+	command_format_options_t format = COMMAND_FORMAT_NONE;
+	char *arg, *peer_ip = NULL, *peer_id = NULL, *ike = NULL, *gateway = NULL;
+	int ret = 0, ike_id = 0;
+
+	while (TRUE)
+	{
+		switch (command_getopt(&arg))
+		{
+			case 'h':
+				return command_usage(NULL);
+			case 'P':
+				format |= COMMAND_FORMAT_PRETTY;
+				/* fall through to raw */
+			case 'r':
+				format |= COMMAND_FORMAT_RAW;
+				continue;
+			case 'i':
+				ike = arg;
+				continue;
+			case 'I':
+				ike_id = atoi(arg);
+				continue;
+			case 'p':
+				peer_ip = arg;
+				continue;
+			case 'd':
+				peer_id = arg;
+				continue;
+			case 'g':
+				gateway = arg;
+				continue;
+			case EOF:
+				break;
+			default:
+				return command_usage("invalid --redirect option");
+		}
+		break;
+	}
+	req = vici_begin("redirect");
+	if (ike)
+	{
+		vici_add_key_valuef(req, "ike", "%s", ike);
+	}
+	if (ike_id)
+	{
+		vici_add_key_valuef(req, "ike-id", "%d", ike_id);
+	}
+	if (peer_ip)
+	{
+		vici_add_key_valuef(req, "peer-ip", "%s", peer_ip);
+	}
+	if (peer_id)
+	{
+		vici_add_key_valuef(req, "peer-id", "%s", peer_id);
+	}
+	if (gateway)
+	{
+		vici_add_key_valuef(req, "gateway", "%s", gateway);
+	}
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		ret = errno;
+		fprintf(stderr, "redirect request failed: %s\n", strerror(errno));
+		return ret;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "redirect reply", format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	else
+	{
+		if (streq(vici_find_str(res, "no", "success"), "yes"))
+		{
+			printf("redirect completed successfully\n");
+		}
+		else
+		{
+			fprintf(stderr, "redirect failed: %s\n",
+					vici_find_str(res, "", "errmsg"));
+			ret = 1;
+		}
+	}
+	vici_free_res(res);
+	return ret;
+}
+
+/**
+ * Register the command.
+ */
+static void __attribute__ ((constructor))reg()
+{
+	command_register((command_t) {
+		redirect, 'd', "redirect", "redirect an IKE_SA",
+		{"--ike <name> | --ike-id <id> | --peer-ip <ip|subnet|range>",
+		 "--peer-id <id|wildcards> | --gateway <ip|fqdn> [--raw|--pretty]"},
+		{
+			{"help",		'h', 0, "show usage information"},
+			{"ike",			'i', 1, "redirect by IKE_SA name"},
+			{"ike-id",		'I', 1, "redirect by IKE_SA unique identifier"},
+			{"peer-ip",		'p', 1, "redirect by client IP"},
+			{"peer-id",		'd', 1, "redirect by IKE_SA name"},
+			{"gateway",		'g', 1, "target gateway (IP or FQDN)"},
+			{"raw",			'r', 0, "dump raw response message"},
+			{"pretty",		'P', 0, "dump raw response message in pretty print"},
+		}
+	});
+}
diff --git a/src/swanctl/commands/stats.c b/src/swanctl/commands/stats.c
index a28ca83..e734c66 100644
--- a/src/swanctl/commands/stats.c
+++ b/src/swanctl/commands/stats.c
@@ -15,8 +15,17 @@
 
 #include "command.h"
 
+#include <collections/hashtable.h>
+
 #include <errno.h>
 
+CALLBACK(list, int,
+	hashtable_t *sa, vici_res_t *res, char *name, void *value, int len)
+{
+	printf(" %.*s", len, value);
+	return 0;
+}
+
 static int stats(vici_conn_t *conn)
 {
 	vici_req_t *req;
@@ -98,6 +107,9 @@ static int stats(vici_conn_t *conn)
 				vici_find_str(res, "", "mallinfo.used"),
 				vici_find_str(res, "", "mallinfo.free"));
 		}
+		printf("loaded plugins:");
+		vici_parse_cb(res, NULL, NULL, list, NULL);
+		printf("\n");
 	}
 	vici_free_res(res);
 	return 0;
diff --git a/src/swanctl/swanctl.8.in b/src/swanctl/swanctl.8.in
index cd033f9..a307460 100644
--- a/src/swanctl/swanctl.8.in
+++ b/src/swanctl/swanctl.8.in
@@ -1,4 +1,4 @@
-.TH SWANCTL 8 "2014-04-28" "@PACKAGE_VERSION@" "strongSwan"
+.TH SWANCTL 8 "2015-11-20" "@PACKAGE_VERSION@" "strongSwan"
 .SH NAME
 swanctl \- strongSwan configuration, control and monitoring command line interface.
 .SH SYNOPSIS
@@ -41,6 +41,10 @@ initiate a connection
 \-\-terminate\fR
 terminate a connection
 .TP
+.B "\-d, \-\-redirect"
+\-\-redirect\fR
+redirect an IKE_SA
+.TP
 .B "\-p, \-\-install"
 install a trap or shunt policy
 .TP
@@ -68,6 +72,9 @@ list stored certificates
 .B "\-A, \-\-list\-pools"
 list loaded pool configurations
 .TP
+.B "\-g, \-\-list\-algs"
+list loaded algorithms and their implementation
+.TP
 .B "\-q, \-\-load\-all"
 (re\-)load credentials, pools, authorities and connections
 .TP
diff --git a/src/swanctl/swanctl.conf b/src/swanctl/swanctl.conf
index c480ce1..428be91 100644
--- a/src/swanctl/swanctl.conf
+++ b/src/swanctl/swanctl.conf
@@ -13,7 +13,7 @@
         # Remote address(es) to use for IKE communication, comma separated.
         # remote_addrs = %any
 
-        # Local UPD port for IKE communication.
+        # Local UDP port for IKE communication.
         # local_port = 500
 
         # Remote UDP port for IKE communication.
@@ -43,7 +43,7 @@
         # Timeout for DPD checks (IKEV1 only).
         # dpd_timeout = 0s
 
-        # Use IKEv1 UDP packet fragmentation (yes, no or force).
+        # Use IKE UDP datagram fragmentation.  (yes, no or force).
         # fragmentation = no
 
         # Send certificate requests payloads (yes or no).
@@ -76,10 +76,19 @@
         # Section for a local authentication round.
         # local<suffix> {
 
+            # Optional numeric identifier by which authentication rounds are
+            # sorted.  If not specified rounds are ordered by their position in
+            # the config file/VICI message.
+            # round = 0
+
             # Comma separated list of certificate candidates to use for
             # authentication.
             # certs =
 
+            # Comma separated list of raw public key candidates to use for
+            # authentication.
+            # pubkeys =
+
             # Authentication to perform locally (pubkey, psk, xauth[-backend] or
             # eap[-method]).
             # auth = pubkey
@@ -102,6 +111,11 @@
         # Section for a remote authentication round.
         # remote<suffix> {
 
+            # Optional numeric identifier by which authentication rounds are
+            # sorted.  If not specified rounds are ordered by their position in
+            # the config file/VICI message.
+            # round = 0
+
             # IKE identity to expect for authentication round.
             # id = %any
 
@@ -115,6 +129,10 @@
             # authentication.
             # cacerts =
 
+            # Comma separated list of raw public keys to accept for
+            # authentication.
+            # pubkeys =
+
             # Certificate revocation policy, (strict, ifuri or relaxed).
             # revocation = relaxed
 
diff --git a/src/swanctl/swanctl.conf.5.main b/src/swanctl/swanctl.conf.5.main
index 6e3842d..a5b2a73 100644
--- a/src/swanctl/swanctl.conf.5.main
+++ b/src/swanctl/swanctl.conf.5.main
@@ -49,7 +49,7 @@ specified.
 
 .TP
 .BR connections.<conn>.local_port " [500]"
-Local UPD port for IKE communication. By default the port of the socket backend
+Local UDP port for IKE communication. By default the port of the socket backend
 is used, which is usually
 .RI "" "500" "."
 If port
@@ -62,7 +62,7 @@ use (socket\-dynamic).
 
 .TP
 .BR connections.<conn>.remote_port " [500]"
-Remote UPD port for IKE communication. If the default of port
+Remote UDP port for IKE communication. If the default of port
 .RI "" "500" ""
 is used,
 automatic IKE port floating to port 4500 is used to work around NAT issues.
@@ -152,17 +152,21 @@ option has no effect on connections using IKE2.
 
 .TP
 .BR connections.<conn>.fragmentation " [no]"
-The default of
+Use IKE fragmentation (proprietary IKEv1 extension or RFC 7383 IKEv2
+fragmentation).  Acceptable  values  are
+.RI "" "yes" ","
+.RI "" "force" ""
+and
 .RI "" "no" ""
-disables IKEv1 fragmentation mechanism,
-.RI "" "yes" ""
-enables it if
-support has been indicated by the peer.
+(the default).
+Fragmented IKE messages sent by a peer are always accepted irrespective of  the
+value  of  this option. If set to
+.RI "" "yes" ","
+and the peer supports it, oversized IKE
+messages will be sent in fragments.  If set  to
 .RI "" "force" ""
-enforces fragmentation if
-required even before the peer had a chance to indicate support for it.
-
-IKE fragmentation is currently not supported with IKEv2.
+(only  supported  for
+IKEv1) the initial IKE message will already be fragmented if required.
 
 .TP
 .BR connections.<conn>.send_certreq " [yes]"
@@ -311,19 +315,36 @@ unique suffix. To define a single authentication round, the suffix may be
 omitted.
 
 .TP
+.BR connections.<conn>.local<suffix>.round " [0]"
+Optional numeric identifier by which authentication rounds are sorted.  If not
+specified rounds are ordered by their position in the config file/VICI message.
+
+.TP
 .BR connections.<conn>.local<suffix>.certs " []"
 Comma separated list of certificate candidates to use for authentication. The
 certificates may use a relative path from the
 .RB "" "swanctl" ""
 .RI "" "x509" ""
-directory, or
-an absolute path.
+directory or an
+absolute path.
 
 The certificate used for authentication is selected based on the received
 certificate request payloads. If no appropriate CA can be located, the first
 certificate is used.
 
 .TP
+.BR connections.<conn>.local<suffix>.pubkeys " []"
+Comma separated list of raw public key candidates to use for authentication. The
+public keys may use a relative path from the
+.RB "" "swanctl" ""
+.RI "" "pubkey" ""
+directory or
+an absolute path.
+
+Even though multiple local public keys could be defined in principle, only the
+first public key in the list is used for authentication.
+
+.TP
 .BR connections.<conn>.local<suffix>.auth " [pubkey]"
 Authentication to perform locally.
 .RI "" "pubkey" ""
@@ -362,6 +383,31 @@ a specific EAP method name may be appended, separated by a dash. An
 EAP module implementing the appropriate method is selected to perform the EAP
 conversation.
 
+If both peers support RFC 7427 ("Signature Authentication in IKEv2") specific
+hash algorithms to be used during IKEv2 authentication may be configured. To do
+so use
+.RI "" "ike:" ""
+followed by a trust chain signature scheme constraint (see
+description of the
+.RB "" "remote" ""
+section's
+.RB "" "auth" ""
+keyword). For example, with
+.RI "" "ike:pubkey\-sha384\-sha256" ""
+a public key signature scheme with either SHA\-384 or
+SHA\-256 would get used for authentication, in that order and depending on the
+hash algorithms supported by the peer. If no specific hash algorithms are
+configured, the default is to prefer an algorithm that matches or exceeds the
+strength of the signature key. If no constraints with
+.RI "" "ike:" ""
+prefix are
+configured any signature scheme constraint (without
+.RI "" "ike:" ""
+prefix) will also
+apply to IKEv2 authentication, unless this is disabled in
+.RB "" "strongswan.conf" "(5)."
+
+
 .TP
 .BR connections.<conn>.local<suffix>.id " []"
 IKE identity to use for authentication round. When using certificate
@@ -432,6 +478,11 @@ unique suffix. To define a single authentication round, the suffix may be
 omitted.
 
 .TP
+.BR connections.<conn>.remote<suffix>.round " [0]"
+Optional numeric identifier by which authentication rounds are sorted.  If not
+specified rounds are ordered by their position in the config file/VICI message.
+
+.TP
 .BR connections.<conn>.remote<suffix>.id " [%any]"
 IKE identity to expect for authentication round. Refer to the
 .RI "" "local" ""
@@ -451,8 +502,8 @@ Comma separated list of certificates to accept for authentication. The
 certificates may use a relative path from the
 .RB "" "swanctl" ""
 .RI "" "x509" ""
-directory, or
-an absolute path.
+directory or an
+absolute path.
 
 .TP
 .BR connections.<conn>.remote<suffix>.cacerts " []"
@@ -460,10 +511,19 @@ Comma separated list of CA certificates to accept for authentication. The
 certificates may use a relative path from the
 .RB "" "swanctl" ""
 .RI "" "x509ca" ""
-directory, or
+directory or
 an absolute path.
 
 .TP
+.BR connections.<conn>.remote<suffix>.pubkeys " []"
+Comma separated list of raw public keys to accept for authentication. The public
+keys may use a relative path from the
+.RB "" "swanctl" ""
+.RI "" "x509" ""
+directory or an
+absolute path.
+
+.TP
 .BR connections.<conn>.remote<suffix>.revocation " [relaxed]"
 Certificate revocation policy for CRL or OCSP revocation.
 
@@ -486,10 +546,40 @@ i.e. it is explicitly known that it is bad.
 .BR connections.<conn>.remote<suffix>.auth " [pubkey]"
 Authentication to expect from remote. See the
 .RB "" "local" ""
-sections
+section's
 .RB "" "auth" ""
 keyword description about the details of supported mechanisms.
 
+To require a trustchain public key strength for the remote side, specify the key
+type followed by the minimum strength in bits (for example
+.RI "" "ecdsa\-384" ""
+or
+.RI "" "rsa\-2048\-ecdsa\-256" ")."
+To limit the acceptable set of hashing algorithms for
+trustchain validation, append hash algorithms to
+.RI "" "pubkey" ""
+or a key strength
+definition (for example
+.RI "" "pubkey\-sha1\-sha256" ""
+or
+.RI "" "rsa\-2048\-ecdsa\-256\-sha256\-sha384\-sha512" ")."
+Unless disabled in
+.RB "" "strongswan.conf" "(5),"
+or explicit IKEv2 signature constraints are configured
+(refer to the description of the
+.RB "" "local" ""
+section's
+.RB "" "auth" ""
+keyword for
+details), such key types and hash algorithms are also applied as constraints
+against IKEv2 signature authentication schemes used by the remote side.
+
+To specify trust chain constraints for EAP\-(T)TLS, append a colon to the EAP
+method, followed by the key type/size and hash algorithm as discussed above
+(e.g.
+.RI "" "eap\-tls:ecdsa\-384\-sha384" ")."
+
+
 .TP
 .B connections.<conn>.children.<child>
 .br
@@ -722,8 +812,8 @@ is negotiated if the preferred mode is not available.
 .RI "" "pass" ""
 and
 .RI "" "drop" ""
-are used to install shunt policies, which explicitly bypass
-the defined traffic from IPsec processing, or drop it, respectively.
+are used to install shunt policies which explicitly bypass the
+defined traffic from IPsec processing or drop it, respectively.
 
 .TP
 .BR connections.<conn>.children.<child>.policies " [yes]"
@@ -856,7 +946,7 @@ which defines the secret type.
 
 It is not recommended to define any private key decryption passphrases, as then
 there is no real security benefit in having encrypted keys. Either store the key
-unencrypted, or enter the keys manually when loading credentials.
+unencrypted or enter the keys manually when loading credentials.
 
 .TP
 .B secrets.eap<suffix>
@@ -872,7 +962,7 @@ as well.
 Value of the EAP/XAuth secret. It may either be an ASCII string, a hex encoded
 string if it has a
 .RI "" "0x" ""
-prefix, or a Base64 encoded string if it has a
+prefix or a Base64 encoded string if it has a
 .RI "" "0s" ""
 prefix in its value.
 
@@ -907,7 +997,7 @@ prefix.
 Value of the IKE preshared secret. It may either be an ASCII string, a hex
 encoded string if it has a
 .RI "" "0x" ""
-prefix, or a Base64 encoded string if it has a
+prefix or a Base64 encoded string if it has a
 .RI "" "0s" ""
 prefix in its value.
 
@@ -1003,7 +1093,7 @@ Section defining a single pool with a unique name.
 .TP
 .BR pools.<name>.addrs " []"
 Subnet or range defining addresses allocated in pool. Accepts a single CIDR
-subnet defining the pool to allocate addresses from, or an address range
+subnet defining the pool to allocate addresses from or an address range
 (<from>\-<to>).  Pools must be unique and non\-overlapping.
 
 .TP
@@ -1042,7 +1132,8 @@ Section defining a certification authority with a unique name.
 The certificates may use a relative path from the
 .RB "" "swanctl" ""
 .RI "" "x509ca" ""
-directory, or an absolute path.
+directory
+or an absolute path.
 
 .TP
 .BR authorities.<name>.crl_uris " []"
diff --git a/src/swanctl/swanctl.h b/src/swanctl/swanctl.h
index cb570cd..560e895 100644
--- a/src/swanctl/swanctl.h
+++ b/src/swanctl/swanctl.h
@@ -2,6 +2,9 @@
  * Copyright (C) 2014 Martin Willi
  * Copyright (C) 2014 revosec AG
  *
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR 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
@@ -42,6 +45,11 @@
 #define SWANCTL_X509AADIR SWANCTLDIR "/x509aa"
 
 /**
+ * Directory for X.509 OCSP Signer certs
+ */
+#define SWANCTL_X509OCSPDIR SWANCTLDIR "/x509ocsp"
+
+/**
  * Directory for X.509 CRLs
  */
 #define SWANCTL_X509CRLDIR SWANCTLDIR "/x509crl"
@@ -52,6 +60,11 @@
 #define SWANCTL_X509ACDIR SWANCTLDIR "/x509ac"
 
 /**
+ * Directory for raw public keys
+ */
+#define SWANCTL_PUBKEYDIR SWANCTLDIR "/pubkey"
+
+/**
  * Directory for RSA private keys
  */
 #define SWANCTL_RSADIR SWANCTLDIR "/rsa"
@@ -62,6 +75,11 @@
 #define SWANCTL_ECDSADIR SWANCTLDIR "/ecdsa"
 
 /**
+ * Directory for BLISS private keys
+ */
+#define SWANCTL_BLISSDIR SWANCTLDIR "/bliss"
+
+/**
  * Directory for PKCS#8 encoded private keys
  */
 #define SWANCTL_PKCS8DIR SWANCTLDIR "/pkcs8"
diff --git a/src/swanctl/swanctl.opt b/src/swanctl/swanctl.opt
index ef38d5d..145fab2 100644
--- a/src/swanctl/swanctl.opt
+++ b/src/swanctl/swanctl.opt
@@ -42,9 +42,9 @@ connections.<conn>.remote_addrs = %any
 	be specified.
 
 connections.<conn>.local_port = 500
-	Local UPD port for IKE communication.
+	Local UDP port for IKE communication.
 
-	Local UPD port for IKE communication. By default the port of the socket
+	Local UDP port for IKE communication. By default the port of the socket
 	backend is used, which is usually _500_. If port _500_ is used, automatic
 	IKE port floating to port 4500 is used to work around NAT issues.
 
@@ -54,7 +54,7 @@ connections.<conn>.local_port = 500
 connections.<conn>.remote_port = 500
 	Remote UDP port for IKE communication.
 
-	Remote UPD port for IKE communication. If the default of port _500_ is used,
+	Remote UDP port for IKE communication. If the default of port _500_ is used,
 	automatic IKE port floating to port 4500 is used to work around NAT issues.
 
 connections.<conn>.proposals = default
@@ -140,14 +140,15 @@ connections.<conn>.dpd_timeout = 0s
 	specified; this option has no effect on connections using IKE2.
 
 connections.<conn>.fragmentation = no
-	Use IKEv1 UDP packet fragmentation (_yes_, _no_ or _force_).
+	Use IKE UDP datagram fragmentation.  (_yes_, _no_ or _force_).
 
-	The default of _no_ disables IKEv1 fragmentation mechanism, _yes_ enables
-	it if support has been indicated by the peer. _force_ enforces
-	fragmentation if required even before the peer had a chance to indicate
-	support for it.
-
-	IKE fragmentation is currently not supported with IKEv2.
+	Use IKE fragmentation (proprietary IKEv1 extension or RFC 7383 IKEv2
+	fragmentation).  Acceptable  values  are _yes_, _force_ and _no_ (the
+	default). Fragmented IKE messages sent by a peer are always accepted
+	irrespective of  the  value  of  this option. If set to _yes_, and the peer
+	supports it, oversized IKE messages will be sent in fragments.  If set  to
+	_force_  (only  supported  for IKEv1) the initial IKE message will already
+	be fragmented if required.
 
 connections.<conn>.send_certreq = yes
 	Send certificate requests payloads (_yes_ or _no_).
@@ -267,17 +268,32 @@ connections.<conn>.local<suffix> {}
 	unique suffix. To define a single authentication round, the suffix may be
 	omitted.
 
+connections.<conn>.local<suffix>.round = 0
+	Optional numeric identifier by which authentication rounds are sorted.  If
+	not specified rounds are ordered by their position in the config file/VICI
+	message.
+
 connections.<conn>.local<suffix>.certs =
 	Comma separated list of certificate candidates to use for authentication.
 
 	Comma separated list of certificate candidates to use for authentication.
 	The certificates may use a relative path from the **swanctl** _x509_
-	directory, or an absolute path.
+	directory or an absolute path.
 
 	The certificate used for authentication is selected based on the received
 	certificate request payloads. If no appropriate CA can be located, the
 	first certificate is used.
 
+connections.<conn>.local<suffix>.pubkeys =
+	Comma separated list of raw public key candidates to use for authentication.
+
+	Comma separated list of raw public key candidates to use for authentication.
+	The public keys may use a relative path from the **swanctl** _pubkey_
+	directory or an absolute path.
+
+	Even though multiple local public keys could be defined in principle, only
+	the	first public key in the list is used for authentication.
+
 connections.<conn>.local<suffix>.auth = pubkey
 	Authentication to perform locally (_pubkey_, _psk_, _xauth[-backend]_ or
 	_eap[-method]_).
@@ -298,6 +314,19 @@ connections.<conn>.local<suffix>.auth = pubkey
 	An EAP module implementing the appropriate method is selected to perform
 	the EAP conversation.
 
+	If both peers support RFC 7427 ("Signature Authentication in IKEv2")
+	specific hash algorithms to be used during IKEv2 authentication may be
+	configured. To do so use _ike:_ followed by a trust chain signature scheme
+	constraint (see description of the **remote** section's **auth** keyword).
+	For example, with _ike:pubkey-sha384-sha256_ a public key signature scheme
+	with either SHA-384 or SHA-256 would get used for authentication, in that
+	order and depending on the hash algorithms supported by the peer. If no
+	specific hash algorithms are configured, the default is to prefer an
+	algorithm that matches or exceeds the strength of the signature key.
+	If no constraints with _ike:_ prefix are configured any signature scheme
+	constraint (without _ike:_ prefix) will also apply to IKEv2 authentication,
+	unless this is disabled in **strongswan.conf**(5).
+
 connections.<conn>.local<suffix>.id =
 	IKE identity to use for authentication round.
 
@@ -350,6 +379,11 @@ connections.<conn>.remote<suffix> {}
 	optional unique suffix. To define a single authentication round, the suffix
 	may be omitted.
 
+connections.<conn>.remote<suffix>.round = 0
+	Optional numeric identifier by which authentication rounds are sorted.  If
+	not specified rounds are ordered by their position in the config file/VICI
+	message.
+
 connections.<conn>.remote<suffix>.id = %any
 	IKE identity to expect for authentication round.
 
@@ -369,14 +403,21 @@ connections.<conn>.remote<suffix>.certs =
 
 	Comma separated list of certificates to accept for authentication.
 	The certificates may use a relative path from the **swanctl** _x509_
-	directory, or an absolute path.
+	directory or an absolute path.
 
 connections.<conn>.remote<suffix>.cacerts =
 	Comma separated list of CA certificates to accept for authentication.
 
 	Comma separated list of CA certificates to accept for authentication.
 	The certificates may use a relative path from the **swanctl** _x509ca_
-	directory, or an absolute path.
+	directory or an absolute path.
+
+connections.<conn>.remote<suffix>.pubkeys =
+	Comma separated list of raw public keys to accept for authentication.
+
+	Comma separated list of raw public keys to accept for authentication.
+	The public keys may use a relative path from the **swanctl** _x509_
+	directory or an absolute path.
 
 connections.<conn>.remote<suffix>.revocation = relaxed
 	Certificate revocation policy, (_strict_, _ifuri_ or _relaxed_).
@@ -397,9 +438,25 @@ connections.<conn>.remote<suffix>.auth = pubkey
 	Authentication to expect from remote (_pubkey_, _psk_, _xauth[-backend]_ or
 	_eap[-method]_).
 
-	Authentication to expect from remote. See the **local** sections **auth**
+	Authentication to expect from remote. See the **local** section's **auth**
 	keyword description about the details of supported mechanisms.
 
+	To require a trustchain public key strength for the remote side, specify the
+	key type followed by the minimum strength in bits (for example _ecdsa-384_
+	or _rsa-2048-ecdsa-256_). To limit the acceptable set of hashing algorithms
+	for trustchain validation, append hash algorithms to _pubkey_ or a key
+	strength definition (for example _pubkey-sha1-sha256_ or
+	_rsa-2048-ecdsa-256-sha256-sha384-sha512_).
+	Unless disabled in **strongswan.conf**(5), or explicit IKEv2 signature
+	constraints are configured (refer to the description of the **local**
+	section's **auth** keyword for details), such key types and hash algorithms
+	are also applied as constraints against IKEv2 signature authentication
+	schemes used by the remote side.
+
+	To specify trust chain constraints for EAP-(T)TLS, append a colon to the
+	EAP method, followed by the key type/size and hash algorithm as discussed
+	above (e.g. _eap-tls:ecdsa-384-sha384_).
+
 connections.<conn>.children.<child> {}
 	CHILD_SA configuration sub-section.
 
@@ -586,8 +643,8 @@ connections.<conn>.children.<child>.mode = tunnel
 	Both _transport_ and _beet_ modes are subject to mode negotiation; _tunnel_
 	mode is negotiated if the preferred mode is not available.
 
-	_pass_ and _drop_ are used to install shunt policies, which explicitly
-	bypass the defined traffic from IPsec processing, or drop it, respectively.
+	_pass_ and _drop_ are used to install shunt policies which explicitly
+	bypass the defined traffic from IPsec processing or drop it, respectively.
 
 connections.<conn>.children.<child>.policies = yes
 	Whether to install IPsec policies or not.
@@ -703,7 +760,7 @@ secrets { # }
 
 	It is not recommended to define any private key decryption passphrases,
 	as then there is no real security benefit in having encrypted keys. Either
-	store the key unencrypted, or enter the keys manually when loading
+	store the key unencrypted or enter the keys manually when loading
 	credentials.
 
 secrets.eap<suffix> { # }
@@ -724,7 +781,7 @@ secrets.eap<suffix>.secret =
 	Value of the EAP/XAuth secret.
 
 	Value of the EAP/XAuth secret. It may either be an ASCII string, a hex
-	encoded string if it has a _0x_ prefix, or a Base64 encoded string if it
+	encoded string if it has a _0x_ prefix or a Base64 encoded string if it
 	has a _0s_ prefix in its value.
 
 secrets.eap<suffix>.id<suffix> =
@@ -744,7 +801,7 @@ secrets.ike<suffix>.secret =
 	Value of the IKE preshared secret.
 
 	Value of the IKE preshared secret. It may either be an ASCII string,
-	a hex encoded string if it has a _0x_ prefix, or a Base64 encoded string if
+	a hex encoded string if it has a _0x_ prefix or a Base64 encoded string if
 	it has a _0s_ prefix in its value.
 
 secrets.ike<suffix>.id<suffix> =
@@ -804,7 +861,7 @@ pools.<name>.addrs =
 	Addresses allocated in pool.
 
 	Subnet or range defining addresses allocated in pool. Accepts a single CIDR
-	subnet defining the pool to allocate addresses from, or an address range
+	subnet defining the pool to allocate addresses from or an address range
 	(<from>-<to>).  Pools must be unique and non-overlapping.
 
 pools.<name>.<attr> =
@@ -827,7 +884,7 @@ authorities.<name>.cacert =
 	CA certificate belonging to the certification authority.
 
 	The certificates may use a relative path from the **swanctl** _x509ca_
-	directory, or an absolute path.
+	directory or an absolute path.
 
 authorities.<name>.crl_uris =
 	Comma-separated list of CRL distribution points
diff --git a/testing/Makefile.in b/testing/Makefile.in
index b66c2be..f797f17 100644
--- a/testing/Makefile.in
+++ b/testing/Makefile.in
@@ -329,6 +329,8 @@ strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
 swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
 systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
 systemd_daemon_LIBS = @systemd_daemon_LIBS@
 systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
diff --git a/testing/do-tests b/testing/do-tests
index c87ba05..2a424e5 100755
--- a/testing/do-tests
+++ b/testing/do-tests
@@ -520,6 +520,14 @@ do
 	    IPTABLES_DSP="iptables -L ; ip6tables -L"
 	fi
 
+	for host in $DBHOSTS
+	do
+	    eval HOSTLOGIN=root@\$ipv4_${host}
+
+		scp $SSHCONF $HOSTLOGIN:/etc/db.d/ipsec.sql \
+		    $TESTRESULTDIR/${host}.ipsec.sql  > /dev/null 2>&1
+	done
+
 	for host in $IPSECHOSTS
 	do
 	    eval HOSTLOGIN=root@\$ipv4_${host}
@@ -531,15 +539,20 @@ do
 			scp $SSHCONF $HOSTLOGIN:/etc/swanctl/swanctl.conf \
 			$TESTRESULTDIR/${host}.swanctl.conf  > /dev/null 2>&1
 
-			for subsys in conns certs pools authorities sas pols
+			for subsys in conns algs certs pools authorities sas pols
 			do
 				ssh $SSHCONF $HOSTLOGIN swanctl --list-$subsys \
 					> $TESTRESULTDIR/${host}.swanctl.$subsys 2>/dev/null
 			done
 
-			# this is quite slow due to allocation stats via leak-detective
 			ssh $SSHCONF $HOSTLOGIN swanctl --stats \
 				> $TESTRESULTDIR/${host}.swanctl.stats 2>/dev/null
+
+			echo "" >> $TESTRESULTDIR/${host}.swanctl.sas
+			cat $TESTRESULTDIR/${host}.swanctl.pols >> \
+				$TESTRESULTDIR/${host}.swanctl.sas
+			cat $TESTRESULTDIR/${host}.swanctl.algs >> \
+				$TESTRESULTDIR/${host}.swanctl.stats
 		else
 		    for file in ipsec.conf ipsec.secrets
 		    do
@@ -552,9 +565,11 @@ do
 				ssh $SSHCONF $HOSTLOGIN ipsec $command \
 			    > $TESTRESULTDIR/${host}.$command 2>/dev/null
 		    done
+		fi
 
-		    scp $SSHCONF $HOSTLOGIN:/etc/ipsec.d/ipsec.sql \
-			$TESTRESULTDIR/${host}.ipsec.sql  > /dev/null 2>&1
+		if (! [ -f $TESTRESULTDIR/${host}.ipsec.sql ] ) then
+			scp $SSHCONF $HOSTLOGIN:/etc/ipsec.d/ipsec.sql \
+				$TESTRESULTDIR/${host}.ipsec.sql  > /dev/null 2>&1
 		fi
 
 	    ssh $SSHCONF $HOSTLOGIN ip -s xfrm policy \
@@ -578,16 +593,16 @@ do
 	    <li><a href="$host.swanctl.conf">swanctl.conf</a></li>
 	    <li><a href="$host.swanctl.conns">swanctl --list-conns</a></li>
 	    <li><a href="$host.swanctl.certs">swanctl --list-certs</a></li>
-	    <li><a href="$host.swanctl.pools">swanctl --list-pools</a></li>
 	    <li><a href="$host.strongswan.conf">strongswan.conf</a></li>
+	    <li><a href="$host.ipsec.sql">ipsec.sql</a></li>
 	  </ul>
 	</td>
 	<td valign="top">
 	  <ul>
-	    <li><a href="$host.swanctl.sas">swanctl --list-sas</a></li>
-	    <li><a href="$host.swanctl.pols">swanctl --list-pols</a></li>
+	    <li><a href="$host.swanctl.sas">swanctl --list-sas|--list-pols</a></li>
+	    <li><a href="$host.swanctl.pools">swanctl --list-pools</a></li>
 	    <li><a href="$host.swanctl.authorities">swanctl --list-authorities</a></li>
-	    <li><a href="$host.swanctl.stats">swanctl --stats</a></li>
+	    <li><a href="$host.swanctl.stats">swanctl --stats|--list-algs</a></li>
 	    <li><a href="$host.daemon.log">daemon.log</a></li>
 	  </ul>
       </td>
diff --git a/testing/hosts/alice/etc/ipsec.d/ipsec.sql b/testing/hosts/alice/etc/ipsec.d/ipsec.sql
index da38e9a..c80052d 100644
--- a/testing/hosts/alice/etc/ipsec.d/ipsec.sql
+++ b/testing/hosts/alice/etc/ipsec.d/ipsec.sql
@@ -1,4 +1,4 @@
 /* strongSwan SQLite database */
 
-/* configuration is read from ipsec.conf   */
-/* credentials are read from ipsec.secrets */
+/* configuration is read from swanctl.conf or ipsec.conf */
+/* credentials  are read from swanctl.conf or ipsec.secrets */
diff --git a/testing/hosts/bob/etc/ipsec.d/ipsec.sql b/testing/hosts/bob/etc/ipsec.d/ipsec.sql
index da38e9a..c80052d 100644
--- a/testing/hosts/bob/etc/ipsec.d/ipsec.sql
+++ b/testing/hosts/bob/etc/ipsec.d/ipsec.sql
@@ -1,4 +1,4 @@
 /* strongSwan SQLite database */
 
-/* configuration is read from ipsec.conf   */
-/* credentials are read from ipsec.secrets */
+/* configuration is read from swanctl.conf or ipsec.conf */
+/* credentials  are read from swanctl.conf or ipsec.secrets */
diff --git a/testing/hosts/carol/etc/ipsec.d/ipsec.sql b/testing/hosts/carol/etc/ipsec.d/ipsec.sql
index da38e9a..c80052d 100644
--- a/testing/hosts/carol/etc/ipsec.d/ipsec.sql
+++ b/testing/hosts/carol/etc/ipsec.d/ipsec.sql
@@ -1,4 +1,4 @@
 /* strongSwan SQLite database */
 
-/* configuration is read from ipsec.conf   */
-/* credentials are read from ipsec.secrets */
+/* configuration is read from swanctl.conf or ipsec.conf */
+/* credentials  are read from swanctl.conf or ipsec.secrets */
diff --git a/testing/hosts/dave/etc/ipsec.d/ipsec.sql b/testing/hosts/dave/etc/ipsec.d/ipsec.sql
index da38e9a..c80052d 100644
--- a/testing/hosts/dave/etc/ipsec.d/ipsec.sql
+++ b/testing/hosts/dave/etc/ipsec.d/ipsec.sql
@@ -1,4 +1,4 @@
 /* strongSwan SQLite database */
 
-/* configuration is read from ipsec.conf   */
-/* credentials are read from ipsec.secrets */
+/* configuration is read from swanctl.conf or ipsec.conf */
+/* credentials  are read from swanctl.conf or ipsec.secrets */
diff --git a/testing/hosts/default/usr/local/bin/expect-connection b/testing/hosts/default/usr/local/bin/expect-connection
index 10a7092..17e2b7f 100755
--- a/testing/hosts/default/usr/local/bin/expect-connection
+++ b/testing/hosts/default/usr/local/bin/expect-connection
@@ -15,10 +15,16 @@ fi
 secs=$2
 [ ! $secs ] && secs=5
 
+cmd="swanctl --list-conns"
+grep 'load.*stroke' /etc/strongswan.conf >/dev/null
+if [ $? -eq 0 ]; then
+	cmd="ipsec statusall"
+fi
+
 let steps=$secs*10
 for i in `seq 1 $steps`
 do
-	ipsec statusall 2>&1 | grep ^[[:space:]]*$1: >/dev/null
+	$cmd 2>&1 | grep ^[[:space:]]*$1: >/dev/null
 	[ $? -eq 0 ] && exit 0
 	sleep 0.1
 done
diff --git a/testing/hosts/moon/etc/ipsec.d/ipsec.sql b/testing/hosts/moon/etc/ipsec.d/ipsec.sql
index da38e9a..c80052d 100644
--- a/testing/hosts/moon/etc/ipsec.d/ipsec.sql
+++ b/testing/hosts/moon/etc/ipsec.d/ipsec.sql
@@ -1,4 +1,4 @@
 /* strongSwan SQLite database */
 
-/* configuration is read from ipsec.conf   */
-/* credentials are read from ipsec.secrets */
+/* configuration is read from swanctl.conf or ipsec.conf */
+/* credentials  are read from swanctl.conf or ipsec.secrets */
diff --git a/testing/hosts/sun/etc/ipsec.d/ipsec.sql b/testing/hosts/sun/etc/ipsec.d/ipsec.sql
index da38e9a..c80052d 100644
--- a/testing/hosts/sun/etc/ipsec.d/ipsec.sql
+++ b/testing/hosts/sun/etc/ipsec.d/ipsec.sql
@@ -1,4 +1,4 @@
 /* strongSwan SQLite database */
 
-/* configuration is read from ipsec.conf   */
-/* credentials are read from ipsec.secrets */
+/* configuration is read from swanctl.conf or ipsec.conf */
+/* credentials  are read from swanctl.conf or ipsec.secrets */
diff --git a/testing/hosts/venus/etc/ipsec.d/ipsec.sql b/testing/hosts/venus/etc/ipsec.d/ipsec.sql
index da38e9a..c80052d 100644
--- a/testing/hosts/venus/etc/ipsec.d/ipsec.sql
+++ b/testing/hosts/venus/etc/ipsec.d/ipsec.sql
@@ -1,4 +1,4 @@
 /* strongSwan SQLite database */
 
-/* configuration is read from ipsec.conf   */
-/* credentials are read from ipsec.secrets */
+/* configuration is read from swanctl.conf or ipsec.conf */
+/* credentials  are read from swanctl.conf or ipsec.secrets */
diff --git a/testing/hosts/winnetou/etc/openssl/generate-crl b/testing/hosts/winnetou/etc/openssl/generate-crl
index 842c3a1..de3c13d 100755
--- a/testing/hosts/winnetou/etc/openssl/generate-crl
+++ b/testing/hosts/winnetou/etc/openssl/generate-crl
@@ -24,6 +24,9 @@ openssl crl -in crl.pem -outform der -out strongswan.crl
 cp strongswan.crl     ${ROOT}
 cp strongswanCert.pem ${ROOT}
 cp index.html         ${ROOT}
+# revoke moon's current CERT
+pki --signcrl --cacert strongswanCert.pem --cakey strongswanKey.pem --lifetime 30 --reason key-compromise --cert newcerts/2B.pem --lastcrl strongswan.crl > strongswan_moon_revoked.crl
+cp strongswan_moon_revoked.crl ${ROOT}
 cd /etc/openssl/research
 openssl ca -gencrl -crldays 15 -config /etc/openssl/research/openssl.cnf -out crl.pem
 openssl crl -in crl.pem -outform der -out research.crl
diff --git a/testing/scripts/recipes/013_strongswan.mk b/testing/scripts/recipes/013_strongswan.mk
index 994acaa..f205df3 100644
--- a/testing/scripts/recipes/013_strongswan.mk
+++ b/testing/scripts/recipes/013_strongswan.mk
@@ -98,7 +98,6 @@ CONFIG_OPTS = \
 	--enable-tkm \
 	--enable-ntru \
 	--enable-lookip \
-	--enable-swanctl \
 	--enable-bliss \
 	--enable-sha3
 
diff --git a/testing/tests/af-alg/alg-camellia/description.txt b/testing/tests/af-alg/alg-camellia/description.txt
index b3515c3..8767978 100644
--- a/testing/tests/af-alg/alg-camellia/description.txt
+++ b/testing/tests/af-alg/alg-camellia/description.txt
@@ -1,4 +1,3 @@
 Roadwarrior <b>carol</b> proposes to gateway <b>moon</b> the IKE cipher suite <b>CAMELLIA_CBC_256 /
-HMAC_SHA2_512_256 / MODP_2048</b> by defining <b>ike=camellia256-sha256-modp2048</b> as well as
-the ESP cipher suite <b>CAMELLIA_CBC_192 / HMAC_SHA1_96</b> by defining <b>esp=camellia192-sha1</b>
-in ipsec.conf. A ping from <b>carol</b> to <b>alice</b> successfully checks the established tunnel.
+HMAC_SHA2_512_256 / PRF_HMAC_SHA2_512 / MODP_3072</b> well as the ESP cipher suite <b>CAMELLIA_CBC_192 / HMAC_SHA384_192</b>.
+A ping from <b>carol</b> to <b>alice</b> successfully checks the established tunnel.
diff --git a/testing/tests/af-alg/alg-camellia/evaltest.dat b/testing/tests/af-alg/alg-camellia/evaltest.dat
index 2096cb9..d88c526 100644
--- a/testing/tests/af-alg/alg-camellia/evaltest.dat
+++ b/testing/tests/af-alg/alg-camellia/evaltest.dat
@@ -1,10 +1,6 @@
-carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw.*ESTABLISHED.*moon.strongswan.org.*carol at strongswan.org::YES
-moon:: ipsec statusall 2> /dev/null::IKE proposal: CAMELLIA_CBC_256/HMAC_SHA2_512_256/PRF_HMAC_SHA2_512/MODP_2048::YES
-carol::ipsec statusall 2> /dev/null::IKE proposal: CAMELLIA_CBC_256/HMAC_SHA2_512_256/PRF_HMAC_SHA2_512/MODP_2048::YES
 carol::ping -c 1 -s 120 -p deadbeef PH_IP_ALICE::128 bytes from PH_IP_ALICE: icmp_req=1::YES
-moon:: ipsec statusall 2> /dev/null::CAMELLIA_CBC_192/HMAC_SHA2_384_192::YES
-carol::ipsec statusall 2> /dev/null::CAMELLIA_CBC_192/HMAC_SHA2_384_192::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=CAMELLIA_CBC encr-keysize=256 integ-alg=HMAC_SHA2_512_256 prf-alg=PRF_HMAC_SHA2_512 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=CAMELLIA_CBC encr-keysize=192 integ-alg=HMAC_SHA2_384_192.*local-ts=\[192. [...]
+moon:: swanctl --list-sas --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=CAMELLIA_CBC encr-keysize=256 integ-alg=HMAC_SHA2_512_256 prf-alg=PRF_HMAC_SHA2_512 dh-group=MODP_3072.*child-sas.*net.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=CAMELLIA_CBC encr-keysize=192 integ-alg=HMAC_SHA2_384_192.*local-ts=\[10.1.0.0/16] remote-t [...]
 moon:: ip xfrm state::enc cbc(camellia)::YES
 carol::ip xfrm state::enc cbc(camellia)::YES
 moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP.*length 208::YES
diff --git a/testing/tests/af-alg/alg-camellia/hosts/carol/etc/ipsec.conf b/testing/tests/af-alg/alg-camellia/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index 11dece4..0000000
--- a/testing/tests/af-alg/alg-camellia/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,22 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-	ike=camellia256-sha512-modp2048!
-	esp=camellia192-sha384!
-
-conn home
-	left=PH_IP_CAROL
-	leftfirewall=yes
-	leftcert=carolCert.pem
-	leftid=carol at strongswan.org
-	right=PH_IP_MOON
-	rightsubnet=10.1.0.0/16
-	rightid=@moon.strongswan.org
-	auto=add 
diff --git a/testing/tests/af-alg/alg-camellia/hosts/carol/etc/strongswan.conf b/testing/tests/af-alg/alg-camellia/hosts/carol/etc/strongswan.conf
index 28b9e58..81a85aa 100644
--- a/testing/tests/af-alg/alg-camellia/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/af-alg/alg-camellia/hosts/carol/etc/strongswan.conf
@@ -1,5 +1,10 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = curl pem pkcs1 af-alg gmp random nonce x509 revocation stroke kernel-netlink socket-default updown
+  load = random nonce pem pkcs1 af-alg gmp x509 revocation kernel-netlink curl socket-default updown vici
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
 }
diff --git a/testing/tests/af-alg/alg-camellia/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/af-alg/alg-camellia/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..acba9ce
--- /dev/null
+++ b/testing/tests/af-alg/alg-camellia/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,27 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = pubkey
+         certs = carolCert.pem
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = camellia192-sha384
+         }
+      }
+      version = 2
+      proposals = camellia256-sha512-modp3072
+   }
+}
diff --git a/testing/tests/af-alg/alg-camellia/hosts/moon/etc/ipsec.conf b/testing/tests/af-alg/alg-camellia/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index ecbb94d..0000000
--- a/testing/tests/af-alg/alg-camellia/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,21 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-	ike=camellia256-sha512-modp2048!
-	esp=camellia192-sha384!
-
-conn rw
-	left=PH_IP_MOON
-	leftfirewall=yes
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftsubnet=10.1.0.0/16
-	right=%any
-	auto=add
diff --git a/testing/tests/af-alg/alg-camellia/hosts/moon/etc/strongswan.conf b/testing/tests/af-alg/alg-camellia/hosts/moon/etc/strongswan.conf
index 28b9e58..81a85aa 100644
--- a/testing/tests/af-alg/alg-camellia/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/af-alg/alg-camellia/hosts/moon/etc/strongswan.conf
@@ -1,5 +1,10 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = curl pem pkcs1 af-alg gmp random nonce x509 revocation stroke kernel-netlink socket-default updown
+  load = random nonce pem pkcs1 af-alg gmp x509 revocation kernel-netlink curl socket-default updown vici
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
 }
diff --git a/testing/tests/af-alg/alg-camellia/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/af-alg/alg-camellia/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..1c06bb2
--- /dev/null
+++ b/testing/tests/af-alg/alg-camellia/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,25 @@
+connections {
+
+   rw {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey
+         certs = moonCert.pem
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = pubkey
+      }
+      children {
+         net {
+            local_ts  = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = camellia192-sha384
+         }
+      }
+      version = 2
+      proposals = camellia256-sha512-modp3072
+   }
+}
diff --git a/testing/tests/af-alg/alg-camellia/posttest.dat b/testing/tests/af-alg/alg-camellia/posttest.dat
index 046d4cf..2fc2bbb 100644
--- a/testing/tests/af-alg/alg-camellia/posttest.dat
+++ b/testing/tests/af-alg/alg-camellia/posttest.dat
@@ -1,4 +1,5 @@
-moon::ipsec stop
-carol::ipsec stop
+carol::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/af-alg/alg-camellia/pretest.dat b/testing/tests/af-alg/alg-camellia/pretest.dat
index de4acbb..41255bc 100644
--- a/testing/tests/af-alg/alg-camellia/pretest.dat
+++ b/testing/tests/af-alg/alg-camellia/pretest.dat
@@ -1,6 +1,7 @@
 moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-carol::ipsec start
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+moon::expect-connection net 
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/af-alg/alg-camellia/test.conf b/testing/tests/af-alg/alg-camellia/test.conf
index 4a5fc47..307c7e9 100644
--- a/testing/tests/af-alg/alg-camellia/test.conf
+++ b/testing/tests/af-alg/alg-camellia/test.conf
@@ -19,3 +19,7 @@ TCPDUMPHOSTS="moon"
 # Used for IPsec logging purposes
 #
 IPSECHOSTS="moon carol"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/af-alg/rw-cert/description.txt b/testing/tests/af-alg/rw-cert/description.txt
index d0c5e92..13f20d1 100644
--- a/testing/tests/af-alg/rw-cert/description.txt
+++ b/testing/tests/af-alg/rw-cert/description.txt
@@ -5,8 +5,8 @@ encryption and hash functions whereas roadwarrior <b>dave</b> uses the default
 <p>
 The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each 
 to gateway <b>moon</b>. The authentication is based on <b>X.509 certificates</b>.
-Upon the successful establishment of the IPsec tunnels, <b>leftfirewall=yes</b>
-automatically inserts iptables-based firewall rules that let pass the tunneled traffic.
+Upon the successful establishment of the IPsec tunnel automatically iptables-based
+firewall rules are inserted which let pass the tunneled traffic.
 In order to test both tunnel and firewall, both <b>carol</b> and <b>dave</b> ping
 the client <b>alice</b> behind the gateway <b>moon</b>.
 
diff --git a/testing/tests/af-alg/rw-cert/evaltest.dat b/testing/tests/af-alg/rw-cert/evaltest.dat
index ba66197..3cd928b 100644
--- a/testing/tests/af-alg/rw-cert/evaltest.dat
+++ b/testing/tests/af-alg/rw-cert/evaltest.dat
@@ -1,15 +1,10 @@
-carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
-dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*dave at strongswan.org.*moon.strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*carol at strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*dave at strongswan.org::YES
-carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-dave:: ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]1}.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]2}.*INSTALLED, TUNNEL::YES
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
 dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=3DES_CBC integ-alg=HMAC_SHA1_96 prf-alg=PRF_HMAC_SHA1 dh-group=MODP_1536.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=3DES_CBC integ-alg=HMAC_SHA1_96.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/16]::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.200/3 [...]
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=3DES_CBC integ-alg=HMAC_SHA1_96 prf-alg=PRF_HMAC_SHA1 dh-group=MODP_1536.*child-sas.*net.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=3DES_CBC integ-alg=HMAC_SHA1_96.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]::YES
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-t [...]
 moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
 moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
 moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
 moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES
-
diff --git a/testing/tests/af-alg/rw-cert/hosts/carol/etc/ipsec.conf b/testing/tests/af-alg/rw-cert/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index 214a8de..0000000
--- a/testing/tests/af-alg/rw-cert/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,22 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-	ike=3des-sha1-modp1536!
-	esp=3des-sha1!
-
-conn home
-	left=PH_IP_CAROL
-	leftcert=carolCert.pem
-	leftid=carol at strongswan.org
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/af-alg/rw-cert/hosts/carol/etc/strongswan.conf b/testing/tests/af-alg/rw-cert/hosts/carol/etc/strongswan.conf
index 2d08b38..3610ac6 100644
--- a/testing/tests/af-alg/rw-cert/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/af-alg/rw-cert/hosts/carol/etc/strongswan.conf
@@ -1,7 +1,12 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = curl test-vectors pem pkcs1 af-alg gmp random nonce x509 revocation ctr ccm gcm stroke kernel-netlink socket-default updown
+  load = random nonce test-vectors pem pkcs1 af-alg gmp x509 revocation curl ctr ccm gcm kernel-netlink socket-default updown vici
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
 
   integrity_test = yes
   crypto_test {
diff --git a/testing/tests/af-alg/rw-cert/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/af-alg/rw-cert/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..22fe14f
--- /dev/null
+++ b/testing/tests/af-alg/rw-cert/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,27 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = pubkey
+         certs = carolCert.pem
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = 3des-sha1-modp1536
+         }
+      }
+      version = 2
+      proposals = 3des-sha1-modp1536 
+   }
+}
diff --git a/testing/tests/af-alg/rw-cert/hosts/dave/etc/ipsec.conf b/testing/tests/af-alg/rw-cert/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 7fa2966..0000000
--- a/testing/tests/af-alg/rw-cert/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,22 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-	ike=aes128-sha256-modp2048!
-	esp=aes128-sha256!
-
-conn home
-	left=PH_IP_DAVE
-	leftcert=daveCert.pem
-	leftid=dave at strongswan.org
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/af-alg/rw-cert/hosts/dave/etc/strongswan.conf b/testing/tests/af-alg/rw-cert/hosts/dave/etc/strongswan.conf
index f7b335e..afa7afe 100644
--- a/testing/tests/af-alg/rw-cert/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/af-alg/rw-cert/hosts/dave/etc/strongswan.conf
@@ -1,11 +1,15 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = test-vectors aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac xcbc ctr ccm gcm stroke kernel-netlink socket-default updown
+  load = random nonce test-vectors aes des sha1 sha2 md5 pem pkcs1 gmp x509 revocation curl hmac xcbc ctr ccm gcm kernel-netlink socket-default updown vici
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
 
   integrity_test = yes
   crypto_test {
-    required = yes
     on_add = yes
   }
 }
diff --git a/testing/tests/af-alg/rw-cert/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/af-alg/rw-cert/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..b3622f5
--- /dev/null
+++ b/testing/tests/af-alg/rw-cert/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,27 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = pubkey
+         certs = daveCert.pem
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128-sha256-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/af-alg/rw-cert/hosts/moon/etc/ipsec.conf b/testing/tests/af-alg/rw-cert/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index fc3eea2..0000000
--- a/testing/tests/af-alg/rw-cert/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,21 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-	ike=aes128-sha256-modp2048,3des-sha1-modp1536!
-	esp=aes128-sha256,3des-sha1!
-
-conn rw
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftsubnet=10.1.0.0/16
-	leftfirewall=yes
-	right=%any
-	auto=add
diff --git a/testing/tests/af-alg/rw-cert/hosts/moon/etc/strongswan.conf b/testing/tests/af-alg/rw-cert/hosts/moon/etc/strongswan.conf
index 2d08b38..3610ac6 100644
--- a/testing/tests/af-alg/rw-cert/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/af-alg/rw-cert/hosts/moon/etc/strongswan.conf
@@ -1,7 +1,12 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = curl test-vectors pem pkcs1 af-alg gmp random nonce x509 revocation ctr ccm gcm stroke kernel-netlink socket-default updown
+  load = random nonce test-vectors pem pkcs1 af-alg gmp x509 revocation curl ctr ccm gcm kernel-netlink socket-default updown vici
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
 
   integrity_test = yes
   crypto_test {
diff --git a/testing/tests/af-alg/rw-cert/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/af-alg/rw-cert/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..ccd247a
--- /dev/null
+++ b/testing/tests/af-alg/rw-cert/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,25 @@
+connections {
+
+   rw {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey
+         certs = moonCert.pem
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = pubkey
+      }
+      children {
+         net {
+            local_ts  = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128-sha256-modp3072,3des-sha1-modp1536
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072,3des-sha1-modp1536 
+   }
+}
diff --git a/testing/tests/af-alg/rw-cert/posttest.dat b/testing/tests/af-alg/rw-cert/posttest.dat
index 1865a1c..d7107cc 100644
--- a/testing/tests/af-alg/rw-cert/posttest.dat
+++ b/testing/tests/af-alg/rw-cert/posttest.dat
@@ -1,6 +1,8 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/af-alg/rw-cert/pretest.dat b/testing/tests/af-alg/rw-cert/pretest.dat
index 855c273..7652f46 100644
--- a/testing/tests/af-alg/rw-cert/pretest.dat
+++ b/testing/tests/af-alg/rw-cert/pretest.dat
@@ -1,11 +1,11 @@
 moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
 dave::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
-moon::expect-connection rw
-carol::expect-connection home
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection net 
+carol::expect-connection home 
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-carol::ipsec up home
-dave::ipsec up home
\ No newline at end of file
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/af-alg/rw-cert/test.conf b/testing/tests/af-alg/rw-cert/test.conf
index f292988..1227b9d 100644
--- a/testing/tests/af-alg/rw-cert/test.conf
+++ b/testing/tests/af-alg/rw-cert/test.conf
@@ -19,3 +19,7 @@ TCPDUMPHOSTS="moon"
 # Used for IPsec logging purposes
 #
 IPSECHOSTS="moon carol dave"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/gcrypt-ikev2/alg-camellia/evaltest.dat b/testing/tests/gcrypt-ikev2/alg-camellia/evaltest.dat
index 5f0bb3c..236647b 100644
--- a/testing/tests/gcrypt-ikev2/alg-camellia/evaltest.dat
+++ b/testing/tests/gcrypt-ikev2/alg-camellia/evaltest.dat
@@ -2,8 +2,8 @@ moon:: ipsec status 2> /dev/null::rw.*ESTABLISHED.*moon.strongswan.org.*carol at st
 carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
 moon:: ipsec status 2> /dev/null::rw.*INSTALLED, TUNNEL::YES
 carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-moon:: ipsec statusall 2> /dev/null::IKE proposal: CAMELLIA_CBC_256/HMAC_SHA2_512_256/PRF_HMAC_SHA2_512/MODP_2048::YES
-carol::ipsec statusall 2> /dev/null::IKE proposal: CAMELLIA_CBC_256/HMAC_SHA2_512_256/PRF_HMAC_SHA2_512/MODP_2048::YES
+moon:: ipsec statusall 2> /dev/null::IKE proposal: CAMELLIA_CBC_256/HMAC_SHA2_512_256/PRF_HMAC_SHA2_512/MODP_3072::YES
+carol::ipsec statusall 2> /dev/null::IKE proposal: CAMELLIA_CBC_256/HMAC_SHA2_512_256/PRF_HMAC_SHA2_512/MODP_3072::YES
 carol::ping -c 1 -s 120 -p deadbeef PH_IP_ALICE::128 bytes from PH_IP_ALICE: icmp_req=1::YES
 moon:: ipsec statusall 2> /dev/null::CAMELLIA_CBC_192/HMAC_SHA2_384_192::YES
 carol::ipsec statusall 2> /dev/null::CAMELLIA_CBC_192/HMAC_SHA2_384_192::YES
diff --git a/testing/tests/gcrypt-ikev2/alg-camellia/hosts/carol/etc/ipsec.conf b/testing/tests/gcrypt-ikev2/alg-camellia/hosts/carol/etc/ipsec.conf
index 11dece4..f0bbfc1 100644
--- a/testing/tests/gcrypt-ikev2/alg-camellia/hosts/carol/etc/ipsec.conf
+++ b/testing/tests/gcrypt-ikev2/alg-camellia/hosts/carol/etc/ipsec.conf
@@ -8,7 +8,7 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev2
-	ike=camellia256-sha512-modp2048!
+	ike=camellia256-sha512-modp3072!
 	esp=camellia192-sha384!
 
 conn home
diff --git a/testing/tests/gcrypt-ikev2/alg-camellia/hosts/moon/etc/ipsec.conf b/testing/tests/gcrypt-ikev2/alg-camellia/hosts/moon/etc/ipsec.conf
index ecbb94d..8481f89 100644
--- a/testing/tests/gcrypt-ikev2/alg-camellia/hosts/moon/etc/ipsec.conf
+++ b/testing/tests/gcrypt-ikev2/alg-camellia/hosts/moon/etc/ipsec.conf
@@ -8,7 +8,7 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev2
-	ike=camellia256-sha512-modp2048!
+	ike=camellia256-sha512-modp3072!
 	esp=camellia192-sha384!
 
 conn rw
diff --git a/testing/tests/gcrypt-ikev2/rw-cert/pretest.dat b/testing/tests/gcrypt-ikev2/rw-cert/pretest.dat
index f1a4b96..15c4ad7 100644
--- a/testing/tests/gcrypt-ikev2/rw-cert/pretest.dat
+++ b/testing/tests/gcrypt-ikev2/rw-cert/pretest.dat
@@ -4,6 +4,7 @@ dave::iptables-restore < /etc/iptables.rules
 moon::ipsec start
 carol::ipsec start
 dave::ipsec start
+moon::expect-connection rw
 carol::expect-connection home
 dave::expect-connection home
 carol::ipsec up home
diff --git a/testing/tests/ha/active-passive/pretest.dat b/testing/tests/ha/active-passive/pretest.dat
index 2bdab28..f82e484 100644
--- a/testing/tests/ha/active-passive/pretest.dat
+++ b/testing/tests/ha/active-passive/pretest.dat
@@ -11,7 +11,6 @@ carol::iptables-restore < /etc/iptables.rules
 dave::iptables-restore < /etc/iptables.rules
 moon::ipsec start
 alice::ipsec start
-moon::ipsec start
 moon::sleep 2
 alice::echo "+1" > /var/run/charon.ha
 carol::ipsec start
diff --git a/testing/tests/ikev1/alg-3des-md5/evaltest.dat b/testing/tests/ikev1/alg-3des-md5/evaltest.dat
index abd29e9..ad0ebd4 100644
--- a/testing/tests/ikev1/alg-3des-md5/evaltest.dat
+++ b/testing/tests/ikev1/alg-3des-md5/evaltest.dat
@@ -5,8 +5,8 @@ carol::ipsec status 2> /dev/null::home.*INSTALLED::YES
 moon:: ipsec statusall 2> /dev/null::rw.*IKE proposal.*3DES_CBC/HMAC_MD5_96/PRF_HMAC_MD5/MODP_1024::YES
 carol::ipsec statusall 2> /dev/null::home.*IKE proposal.*3DES_CBC/HMAC_MD5_96/PRF_HMAC_MD5/MODP_1024::YES
 carol::ping -c 1 -s 120 -p deadbeef PH_IP_ALICE::128 bytes from PH_IP_ALICE: icmp_req=1::YES
-moon:: ipsec statusall 2> /dev/null::rw.*3DES_CBC/HMAC_MD5_96,::YES
-carol::ipsec statusall 2> /dev/null::home.*3DES_CBC/HMAC_MD5_96,::YES
+moon:: ipsec statusall 2> /dev/null::rw.*3DES_CBC/HMAC_MD5_96/MODP_1024,::YES
+carol::ipsec statusall 2> /dev/null::home.*3DES_CBC/HMAC_MD5_96/MODP_1024,::YES
 moon:: ip xfrm state::enc cbc(des3_ede)::YES
 carol::ip xfrm state::enc cbc(des3_ede)::YES
 moon:: ip xfrm state::auth-trunc hmac(md5)::YES
diff --git a/testing/tests/ikev1/alg-sha256/evaltest.dat b/testing/tests/ikev1/alg-sha256/evaltest.dat
index eba8567..364d89f 100644
--- a/testing/tests/ikev1/alg-sha256/evaltest.dat
+++ b/testing/tests/ikev1/alg-sha256/evaltest.dat
@@ -2,11 +2,11 @@ moon:: ipsec status 2> /dev/null::rw.*ESTABLISHED.*moon.strongswan.org.*carol at st
 carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
 moon:: ipsec status 2> /dev/null::rw.*INSTALLED, TUNNEL::YES
 carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-moon:: ipsec statusall 2> /dev/null::rw.*IKE proposal.*AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048::YES
-carol::ipsec statusall 2> /dev/null::home.*IKE proposal.*AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048::YES
+moon:: ipsec statusall 2> /dev/null::rw.*IKE proposal.*AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072::YES
+carol::ipsec statusall 2> /dev/null::home.*IKE proposal.*AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072::YES
 carol::ping -c 1 -s 120 -p deadbeef PH_IP_ALICE::128 bytes from PH_IP_ALICE: icmp_req=1::YES
-moon:: ipsec statusall 2> /dev/null::rw.*AES_CBC_128/HMAC_SHA2_256_128,::YES
-carol::ipsec statusall 2> /dev/null::home.*AES_CBC_128/HMAC_SHA2_256_128,::YES
+moon:: ipsec statusall 2> /dev/null::rw.*AES_CBC_128/HMAC_SHA2_256_128/MODP_3072,::YES
+carol::ipsec statusall 2> /dev/null::home.*AES_CBC_128/HMAC_SHA2_256_128/MODP_3072,::YES
 moon:: ip xfrm state::auth-trunc hmac(sha256)::YES
 carol::ip xfrm state::auth-trunc hmac(sha256)::YES
 moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP.*length 200::YES
diff --git a/testing/tests/ikev1/alg-sha256/hosts/carol/etc/ipsec.conf b/testing/tests/ikev1/alg-sha256/hosts/carol/etc/ipsec.conf
index 73e2571..1c22797 100644
--- a/testing/tests/ikev1/alg-sha256/hosts/carol/etc/ipsec.conf
+++ b/testing/tests/ikev1/alg-sha256/hosts/carol/etc/ipsec.conf
@@ -8,8 +8,8 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev1
-	ike=aes128-sha256-modp2048!
-	esp=aes128-sha256-modp2048!
+	ike=aes128-sha256-modp3072!
+	esp=aes128-sha256-modp3072!
 
 conn home
 	left=PH_IP_CAROL
diff --git a/testing/tests/ikev1/alg-sha256/hosts/moon/etc/ipsec.conf b/testing/tests/ikev1/alg-sha256/hosts/moon/etc/ipsec.conf
index 0a6f48e..177aebf 100644
--- a/testing/tests/ikev1/alg-sha256/hosts/moon/etc/ipsec.conf
+++ b/testing/tests/ikev1/alg-sha256/hosts/moon/etc/ipsec.conf
@@ -8,8 +8,8 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev1
-	ike=aes128-sha256-modp2048!
-	esp=aes128-sha256-modp2048!
+	ike=aes128-sha256-modp3072!
+	esp=aes128-sha256-modp3072!
 
 conn rw
 	left=PH_IP_MOON
diff --git a/testing/tests/ikev1/alg-sha384/evaltest.dat b/testing/tests/ikev1/alg-sha384/evaltest.dat
index 3b24217..14f0ba4 100644
--- a/testing/tests/ikev1/alg-sha384/evaltest.dat
+++ b/testing/tests/ikev1/alg-sha384/evaltest.dat
@@ -5,8 +5,8 @@ carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
 moon:: ipsec statusall 2> /dev/null::rw.*IKE proposal.*AES_CBC_192/HMAC_SHA2_384_192/PRF_HMAC_SHA2_384/MODP_3072::YES
 carol::ipsec statusall 2> /dev/null::home.*IKE proposal.*AES_CBC_192/HMAC_SHA2_384_192/PRF_HMAC_SHA2_384/MODP_3072::YES
 carol::ping -c 1 -s 120 -p deadbeef PH_IP_ALICE::128 bytes from PH_IP_ALICE: icmp_req=1::YES
-moon:: ipsec statusall 2> /dev/null::rw.*AES_CBC_192/HMAC_SHA2_384_192,::YES
-carol::ipsec statusall 2> /dev/null::home.*AES_CBC_192/HMAC_SHA2_384_192,::YES
+moon:: ipsec statusall 2> /dev/null::rw.*AES_CBC_192/HMAC_SHA2_384_192/MODP_3072,::YES
+carol::ipsec statusall 2> /dev/null::home.*AES_CBC_192/HMAC_SHA2_384_192/MODP_3072,::YES
 moon:: ip xfrm state::auth-trunc hmac(sha384)::YES
 carol::ip xfrm state::auth-trunc hmac(sha384)::YES
 moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP.*length 208::YES
diff --git a/testing/tests/ikev1/alg-sha512/evaltest.dat b/testing/tests/ikev1/alg-sha512/evaltest.dat
index 6bdceeb..6f8c05d 100644
--- a/testing/tests/ikev1/alg-sha512/evaltest.dat
+++ b/testing/tests/ikev1/alg-sha512/evaltest.dat
@@ -5,8 +5,8 @@ carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
 moon:: ipsec statusall 2> /dev/null::rw.*IKE proposal.*AES_CBC_256/HMAC_SHA2_512_256/PRF_HMAC_SHA2_512/MODP_4096::YES
 carol::ipsec statusall 2> /dev/null::home.*IKE proposal.*AES_CBC_256/HMAC_SHA2_512_256/PRF_HMAC_SHA2_512/MODP_4096::YES
 carol::ping -c 1 -s 120 -p deadbeef PH_IP_ALICE::128 bytes from PH_IP_ALICE: icmp_req=1::YES
-moon:: ipsec statusall 2> /dev/null::rw.*AES_CBC_256/HMAC_SHA2_512_256,::YES
-carol::ipsec statusall 2> /dev/null::home.*AES_CBC_256/HMAC_SHA2_512_256,::YES
+moon:: ipsec statusall 2> /dev/null::rw.*AES_CBC_256/HMAC_SHA2_512_256/MODP_4096,::YES
+carol::ipsec statusall 2> /dev/null::home.*AES_CBC_256/HMAC_SHA2_512_256/MODP_4096,::YES
 moon:: ip xfrm state::auth-trunc hmac(sha512)::YES
 carol::ip xfrm state::auth-trunc hmac(sha512)::YES
 moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP.*length 216::YES
diff --git a/testing/tests/ikev1/ip-pool-db/hosts/moon/etc/strongswan.conf b/testing/tests/ikev1/ip-pool-db/hosts/moon/etc/strongswan.conf
index 6c22fd5..7d97dd2 100644
--- a/testing/tests/ikev1/ip-pool-db/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/ikev1/ip-pool-db/hosts/moon/etc/strongswan.conf
@@ -2,9 +2,7 @@
 
 charon {
   load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac xcbc stroke kernel-netlink socket-default sqlite attr-sql updown
-}
 
-libhydra {
   plugins {
     attr-sql {
       database = sqlite:///etc/db.d/ipsec.db
diff --git a/testing/tests/ikev1/xauth-rsa-eap-md5-radius/evaltest.dat b/testing/tests/ikev1/xauth-rsa-eap-md5-radius/evaltest.dat
index d568273..fe148cd 100644
--- a/testing/tests/ikev1/xauth-rsa-eap-md5-radius/evaltest.dat
+++ b/testing/tests/ikev1/xauth-rsa-eap-md5-radius/evaltest.dat
@@ -1,4 +1,4 @@
-carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA successful::YES
+carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA_EMSA_PKCS1_NULL successful::YES
 moon:: cat /var/log/daemon.log::RADIUS authentication of 'carol at strongswan.org' successful::YES
 moon:: cat /var/log/daemon.log::XAuth authentication of 'carol at strongswan.org' successful::YES
 moon:: ipsec status 2> /dev/null::rw.*ESTABLISHED.*moon.strongswan.org.*carol at strongswan.org::YES
diff --git a/testing/tests/ikev1/xauth-rsa-radius/evaltest.dat b/testing/tests/ikev1/xauth-rsa-radius/evaltest.dat
index ee60292..a88debd 100644
--- a/testing/tests/ikev1/xauth-rsa-radius/evaltest.dat
+++ b/testing/tests/ikev1/xauth-rsa-radius/evaltest.dat
@@ -1,4 +1,4 @@
-carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA successful::YES
+carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA_EMSA_PKCS1_NULL successful::YES
 moon:: cat /var/log/daemon.log::XAuth authentication of 'carol at strongswan.org' successful::YES
 moon:: ipsec status 2> /dev/null::rw.*ESTABLISHED.*moon.strongswan.org.*carol at strongswan.org::YES
 carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
diff --git a/testing/tests/ikev2/alg-aes-xcbc/evaltest.dat b/testing/tests/ikev2/alg-aes-xcbc/evaltest.dat
index f110183..c896b5f 100644
--- a/testing/tests/ikev2/alg-aes-xcbc/evaltest.dat
+++ b/testing/tests/ikev2/alg-aes-xcbc/evaltest.dat
@@ -2,8 +2,8 @@ moon:: ipsec status 2> /dev/null::rw.*ESTABLISHED.*moon.strongswan.org.*carol at st
 carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
 moon:: ipsec status 2> /dev/null::rw.*INSTALLED, TUNNEL::YES
 carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-moon:: ipsec statusall 2> /dev/null::rw.*IKE proposal.*AES_CBC_128/AES_XCBC_96/PRF_AES128_XCBC/MODP_2048::YES
-carol::ipsec statusall 2> /dev/null::home.*IKE proposal.*AES_CBC_128/AES_XCBC_96/PRF_AES128_XCBC/MODP_2048::YES
+moon:: ipsec statusall 2> /dev/null::rw.*IKE proposal.*AES_CBC_128/AES_XCBC_96/PRF_AES128_XCBC/MODP_3072::YES
+carol::ipsec statusall 2> /dev/null::home.*IKE proposal.*AES_CBC_128/AES_XCBC_96/PRF_AES128_XCBC/MODP_3072::YES
 carol::ping -c 1 -s 120 -p deadbeef PH_IP_ALICE::128 bytes from PH_IP_ALICE: icmp_req=1::YES
 moon:: ipsec statusall 2> /dev/null::rw.*AES_CBC_128/AES_XCBC_96,::YES
 carol::ipsec statusall 2> /dev/null::home.*AES_CBC_128/AES_XCBC_96,::YES
diff --git a/testing/tests/ikev2/alg-aes-xcbc/hosts/carol/etc/ipsec.conf b/testing/tests/ikev2/alg-aes-xcbc/hosts/carol/etc/ipsec.conf
index 74668e7..c9e9e92 100644
--- a/testing/tests/ikev2/alg-aes-xcbc/hosts/carol/etc/ipsec.conf
+++ b/testing/tests/ikev2/alg-aes-xcbc/hosts/carol/etc/ipsec.conf
@@ -8,8 +8,8 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev2
-	ike=aes128-aesxcbc-modp2048!
-	esp=aes128-aesxcbc-modp2048!
+	ike=aes128-aesxcbc-modp3072!
+	esp=aes128-aesxcbc-modp3072!
 
 conn home
 	left=PH_IP_CAROL
diff --git a/testing/tests/ikev2/alg-aes-xcbc/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/alg-aes-xcbc/hosts/moon/etc/ipsec.conf
index 3cda729..4e4a932 100644
--- a/testing/tests/ikev2/alg-aes-xcbc/hosts/moon/etc/ipsec.conf
+++ b/testing/tests/ikev2/alg-aes-xcbc/hosts/moon/etc/ipsec.conf
@@ -8,8 +8,8 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev2
-	ike=aes128-aesxcbc-modp2048!
-	esp=aes128-aesxcbc-modp2048!
+	ike=aes128-aesxcbc-modp3072!
+	esp=aes128-aesxcbc-modp3072!
 
 conn rw
 	left=PH_IP_MOON
diff --git a/testing/tests/ikev2/alg-sha256-96/evaltest.dat b/testing/tests/ikev2/alg-sha256-96/evaltest.dat
index 6c4e237..8ad0fb2 100644
--- a/testing/tests/ikev2/alg-sha256-96/evaltest.dat
+++ b/testing/tests/ikev2/alg-sha256-96/evaltest.dat
@@ -4,8 +4,8 @@ moon:: ipsec status 2> /dev/null::rw.*INSTALLED, TUNNEL::YES
 carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
 moon:: cat /var/log/daemon.log::received strongSwan vendor ID::YES
 carol::cat /var/log/daemon.log::received strongSwan vendor ID::YES
-moon:: ipsec statusall 2> /dev/null::rw.*IKE proposal.*AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048::YES
-carol::ipsec statusall 2> /dev/null::home.*IKE proposal.*AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048::YES
+moon:: ipsec statusall 2> /dev/null::rw.*IKE proposal.*AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072::YES
+carol::ipsec statusall 2> /dev/null::home.*IKE proposal.*AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072::YES
 carol::ping -c 1 -s 120 -p deadbeef PH_IP_ALICE::128 bytes from PH_IP_ALICE: icmp_req=1::YES
 moon:: ipsec statusall 2> /dev/null::rw.*AES_CBC_128/HMAC_SHA2_256_96,::YES
 carol::ipsec statusall 2> /dev/null::home.*AES_CBC_128/HMAC_SHA2_256_96,::YES
diff --git a/testing/tests/ikev2/alg-sha256-96/hosts/carol/etc/ipsec.conf b/testing/tests/ikev2/alg-sha256-96/hosts/carol/etc/ipsec.conf
index 0d3b9fd..90a1436 100644
--- a/testing/tests/ikev2/alg-sha256-96/hosts/carol/etc/ipsec.conf
+++ b/testing/tests/ikev2/alg-sha256-96/hosts/carol/etc/ipsec.conf
@@ -8,8 +8,8 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev2
-	ike=aes128-sha256-modp2048!
-	esp=aes128-sha256_96-modp2048!
+	ike=aes128-sha256-modp3072!
+	esp=aes128-sha256_96-modp3072!
 
 conn home
 	left=PH_IP_CAROL
diff --git a/testing/tests/ikev2/alg-sha256-96/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/alg-sha256-96/hosts/moon/etc/ipsec.conf
index b0a5c46..e0b2625 100644
--- a/testing/tests/ikev2/alg-sha256-96/hosts/moon/etc/ipsec.conf
+++ b/testing/tests/ikev2/alg-sha256-96/hosts/moon/etc/ipsec.conf
@@ -8,8 +8,8 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev2
-	ike=aes128-sha256-modp2048!
-	esp=aes128-sha256_96-modp2048!
+	ike=aes128-sha256-modp3072!
+	esp=aes128-sha256_96-modp3072!
 
 conn rw
 	left=PH_IP_MOON
diff --git a/testing/tests/ikev2/alg-sha256/evaltest.dat b/testing/tests/ikev2/alg-sha256/evaltest.dat
index eba8567..c826c3f 100644
--- a/testing/tests/ikev2/alg-sha256/evaltest.dat
+++ b/testing/tests/ikev2/alg-sha256/evaltest.dat
@@ -2,8 +2,8 @@ moon:: ipsec status 2> /dev/null::rw.*ESTABLISHED.*moon.strongswan.org.*carol at st
 carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
 moon:: ipsec status 2> /dev/null::rw.*INSTALLED, TUNNEL::YES
 carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-moon:: ipsec statusall 2> /dev/null::rw.*IKE proposal.*AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048::YES
-carol::ipsec statusall 2> /dev/null::home.*IKE proposal.*AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048::YES
+moon:: ipsec statusall 2> /dev/null::rw.*IKE proposal.*AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072::YES
+carol::ipsec statusall 2> /dev/null::home.*IKE proposal.*AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072::YES
 carol::ping -c 1 -s 120 -p deadbeef PH_IP_ALICE::128 bytes from PH_IP_ALICE: icmp_req=1::YES
 moon:: ipsec statusall 2> /dev/null::rw.*AES_CBC_128/HMAC_SHA2_256_128,::YES
 carol::ipsec statusall 2> /dev/null::home.*AES_CBC_128/HMAC_SHA2_256_128,::YES
diff --git a/testing/tests/ikev2/alg-sha256/hosts/carol/etc/ipsec.conf b/testing/tests/ikev2/alg-sha256/hosts/carol/etc/ipsec.conf
index 22d2cd3..6890ea4 100644
--- a/testing/tests/ikev2/alg-sha256/hosts/carol/etc/ipsec.conf
+++ b/testing/tests/ikev2/alg-sha256/hosts/carol/etc/ipsec.conf
@@ -8,8 +8,8 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev2
-	ike=aes128-sha256-modp2048!
-	esp=aes128-sha256-modp2048!
+	ike=aes128-sha256-modp3072!
+	esp=aes128-sha256-modp3072!
 
 conn home
 	left=PH_IP_CAROL
diff --git a/testing/tests/ikev2/alg-sha256/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/alg-sha256/hosts/moon/etc/ipsec.conf
index 543374d..5831118 100644
--- a/testing/tests/ikev2/alg-sha256/hosts/moon/etc/ipsec.conf
+++ b/testing/tests/ikev2/alg-sha256/hosts/moon/etc/ipsec.conf
@@ -8,8 +8,8 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev2
-	ike=aes128-sha256-modp2048!
-	esp=aes128-sha256-modp2048!
+	ike=aes128-sha256-modp3072!
+	esp=aes128-sha256-modp3072!
 
 conn rw
 	left=PH_IP_MOON
diff --git a/testing/tests/ikev2/ip-pool-db/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/ip-pool-db/hosts/moon/etc/strongswan.conf
index 6c22fd5..7d97dd2 100644
--- a/testing/tests/ikev2/ip-pool-db/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/ikev2/ip-pool-db/hosts/moon/etc/strongswan.conf
@@ -2,9 +2,7 @@
 
 charon {
   load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac xcbc stroke kernel-netlink socket-default sqlite attr-sql updown
-}
 
-libhydra {
   plugins {
     attr-sql {
       database = sqlite:///etc/db.d/ipsec.db
diff --git a/testing/tests/ikev2/ip-split-pools-db/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/ip-split-pools-db/hosts/moon/etc/strongswan.conf
index 6c22fd5..7d97dd2 100644
--- a/testing/tests/ikev2/ip-split-pools-db/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/ikev2/ip-split-pools-db/hosts/moon/etc/strongswan.conf
@@ -2,9 +2,7 @@
 
 charon {
   load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac xcbc stroke kernel-netlink socket-default sqlite attr-sql updown
-}
 
-libhydra {
   plugins {
     attr-sql {
       database = sqlite:///etc/db.d/ipsec.db
diff --git a/testing/tests/ikev2/ip-two-pools-db/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/ip-two-pools-db/hosts/moon/etc/strongswan.conf
index cf3b0d8..b238646 100644
--- a/testing/tests/ikev2/ip-two-pools-db/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/ikev2/ip-two-pools-db/hosts/moon/etc/strongswan.conf
@@ -2,9 +2,7 @@
 
 charon {
   load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac xcbc stroke sqlite attr-sql kernel-netlink socket-default updown
-}
 
-libhydra {
   plugins {
     attr-sql {
       database = sqlite:///etc/db.d/ipsec.db
diff --git a/testing/tests/ikev2/ip-two-pools-mixed/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/ip-two-pools-mixed/hosts/moon/etc/strongswan.conf
index cf3b0d8..b238646 100644
--- a/testing/tests/ikev2/ip-two-pools-mixed/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/ikev2/ip-two-pools-mixed/hosts/moon/etc/strongswan.conf
@@ -2,9 +2,7 @@
 
 charon {
   load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac xcbc stroke sqlite attr-sql kernel-netlink socket-default updown
-}
 
-libhydra {
   plugins {
     attr-sql {
       database = sqlite:///etc/db.d/ipsec.db
diff --git a/testing/tests/ikev2/ip-two-pools-v4v6-db/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/ip-two-pools-v4v6-db/hosts/moon/etc/strongswan.conf
index 5176e2a..da157a5 100644
--- a/testing/tests/ikev2/ip-two-pools-v4v6-db/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/ikev2/ip-two-pools-v4v6-db/hosts/moon/etc/strongswan.conf
@@ -2,9 +2,7 @@
 
 charon {
   load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite attr-sql
-}
 
-libhydra {
   plugins {
     attr-sql {
       database = sqlite:///etc/db.d/ipsec.db
diff --git a/testing/tests/ikev2/ip-two-pools/pretest.dat b/testing/tests/ikev2/ip-two-pools/pretest.dat
index 56c1785..3aa610b 100644
--- a/testing/tests/ikev2/ip-two-pools/pretest.dat
+++ b/testing/tests/ikev2/ip-two-pools/pretest.dat
@@ -1,8 +1,8 @@
 moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
 alice::iptables-restore < /etc/iptables.rules
-carol::ipsec start
 moon::ipsec start
+carol::ipsec start
 alice::ipsec start
 carol::expect-connection home
 carol::ipsec up home
diff --git a/testing/tests/ikev2/reauth-mbb-revoked/description.txt b/testing/tests/ikev2/reauth-mbb-revoked/description.txt
new file mode 100644
index 0000000..4e27a0b
--- /dev/null
+++ b/testing/tests/ikev2/reauth-mbb-revoked/description.txt
@@ -0,0 +1,15 @@
+This scenario tests <b>make-before-break reauthentication</b> using overlapping
+IKE_SAs by setting the <i>make_before_break</i> strongswan.conf option. The
+initiator <b>carol</b> reauthenticates the IKE_SA with host <b>moon</b> using
+<b>ikelifetime=10s</b>, but does not close the old IKE_SA before the replacement
+CHILD_SA is in place. A constant ping from <b>carol</b> to client <b>alice</b>
+hiding in the subnet behind <b>moon</b> tests if the CHILD_SA works during the
+whole procedure.
+<p/>
+Because the responder is always able to install CHILD_SAs before the initiator
+is, some traffic sent by the responder over such a CHILD_SA might get dropped by
+the initiator (until it also installed the CHILD_SA).  This is particularly
+problematic if OCSP/CRL checks are delayed or if they can also be done via the
+IPsec tunnel once it's established.  Therefore, online OCSP/CRL checks are
+suspended during the reauthentication and done afterwards. This is verified here
+by revoking the responder's certificate after the SA got initially established.
diff --git a/testing/tests/ikev2/reauth-mbb-revoked/evaltest.dat b/testing/tests/ikev2/reauth-mbb-revoked/evaltest.dat
new file mode 100644
index 0000000..8fe9a23
--- /dev/null
+++ b/testing/tests/ikev2/reauth-mbb-revoked/evaltest.dat
@@ -0,0 +1,10 @@
+winnetou::cp /var/www/strongswan.crl /var/www/strongswan.crl.bak
+winnetou::cp /var/www/strongswan_moon_revoked.crl /var/www/strongswan.crl
+carol::ipsec purgecrls
+moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*carol at strongswan.org::YES
+carol::ipsec status 2> /dev/null::home\[1]: ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
+carol::sleep 6
+carol::cat /var/log/daemon.log::certificate was revoked.*key compromise::YES
+carol::cat /var/log/daemon.log::peer certificate verification failed, deleting SA::YES
+moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*carol at strongswan.org::NO
+carol::ipsec status 2> /dev/null::home\[2]: ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::NO
diff --git a/testing/tests/ikev2/reauth-mbb-revoked/hosts/carol/etc/ipsec.conf b/testing/tests/ikev2/reauth-mbb-revoked/hosts/carol/etc/ipsec.conf
new file mode 100644
index 0000000..ec2b41d
--- /dev/null
+++ b/testing/tests/ikev2/reauth-mbb-revoked/hosts/carol/etc/ipsec.conf
@@ -0,0 +1,21 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+	strictcrlpolicy=yes
+
+conn %default
+	keylife=20m
+	ikelifetime=10s
+	rekeymargin=5s
+	rekeyfuzz=0%
+	keyingtries=1
+
+conn home
+	left=PH_IP_CAROL
+	leftcert=carolCert.pem
+	leftid=carol at strongswan.org
+	right=PH_IP_MOON
+	rightid=@moon.strongswan.org
+	rightsubnet=10.1.0.0/16
+	keyexchange=ikev2
+	auto=add
diff --git a/testing/tests/ikev2/reauth-mbb-revoked/hosts/carol/etc/strongswan.conf b/testing/tests/ikev2/reauth-mbb-revoked/hosts/carol/etc/strongswan.conf
new file mode 100644
index 0000000..f89437e
--- /dev/null
+++ b/testing/tests/ikev2/reauth-mbb-revoked/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,7 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac xcbc stroke kernel-netlink socket-default updown
+
+  make_before_break = yes
+}
diff --git a/testing/tests/ikev2/reauth-mbb-revoked/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/reauth-mbb-revoked/hosts/moon/etc/ipsec.conf
new file mode 100644
index 0000000..93ae34c
--- /dev/null
+++ b/testing/tests/ikev2/reauth-mbb-revoked/hosts/moon/etc/ipsec.conf
@@ -0,0 +1,19 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+	strictcrlpolicy=yes
+
+conn %default
+	ikelifetime=30m
+	keylife=20m
+	rekeymargin=0s
+	keyingtries=1
+
+conn rw
+	left=PH_IP_MOON
+	leftcert=moonCert.pem
+	leftid=@moon.strongswan.org
+	leftsubnet=10.1.0.0/16
+	right=%any
+	keyexchange=ikev2
+	auto=add
diff --git a/testing/tests/ikev2/reauth-mbb-revoked/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/reauth-mbb-revoked/hosts/moon/etc/strongswan.conf
new file mode 100644
index 0000000..f585edf
--- /dev/null
+++ b/testing/tests/ikev2/reauth-mbb-revoked/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,5 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac xcbc stroke kernel-netlink socket-default updown
+}
diff --git a/testing/tests/ikev2/reauth-mbb-revoked/posttest.dat b/testing/tests/ikev2/reauth-mbb-revoked/posttest.dat
new file mode 100644
index 0000000..d0d5915
--- /dev/null
+++ b/testing/tests/ikev2/reauth-mbb-revoked/posttest.dat
@@ -0,0 +1,3 @@
+winnetou::cp /var/www/strongswan.crl.bak /var/www/strongswan.crl
+moon::ipsec stop
+carol::ipsec stop
diff --git a/testing/tests/ikev2/reauth-mbb-revoked/pretest.dat b/testing/tests/ikev2/reauth-mbb-revoked/pretest.dat
new file mode 100644
index 0000000..3a1982f
--- /dev/null
+++ b/testing/tests/ikev2/reauth-mbb-revoked/pretest.dat
@@ -0,0 +1,4 @@
+moon::ipsec start
+carol::ipsec start
+carol::expect-connection home
+carol::ipsec up home
diff --git a/testing/tests/af-alg/alg-camellia/test.conf b/testing/tests/ikev2/reauth-mbb-revoked/test.conf
similarity index 100%
copy from testing/tests/af-alg/alg-camellia/test.conf
copy to testing/tests/ikev2/reauth-mbb-revoked/test.conf
diff --git a/testing/tests/ikev2/redirect-active/description.txt b/testing/tests/ikev2/redirect-active/description.txt
new file mode 100644
index 0000000..942c66e
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/description.txt
@@ -0,0 +1,8 @@
+The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each
+to gateway <b>alice</b>, which identifies itself as <b>mars</b>.
+Host <b>venus</b> in the subnet behind this gateway uses gateway <b>moon</b> as
+default gateway, so it is not fully reachable by the two roadwarriors.
+Then both SAs are actively redirected with the <em>swanctl --redirect</em>
+command to gateway <b>moon</b> (also identified as <b>mars</b>) using the
+mechanism described in <b>RFC 5685</b> enabling the roadwarriors to
+ping <b>venus</b>.
diff --git a/testing/tests/ikev2/redirect-active/evaltest.dat b/testing/tests/ikev2/redirect-active/evaltest.dat
new file mode 100644
index 0000000..6d84173
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/evaltest.dat
@@ -0,0 +1,28 @@
+alice::ipsec status 2> /dev/null::rw\[1].*ESTABLISHED.*mars.strongswan.org.*carol at strongswan.org::YES
+alice::ipsec status 2> /dev/null::rw\[2].*ESTABLISHED.*mars.strongswan.org.*dave at strongswan.org::YES
+carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*mars.strongswan.org::YES
+dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*dave at strongswan.org.*mars.strongswan.org::YES
+carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
+dave:: ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
+alice::swanctl --redirect --peer-ip PH_IP_CAROL --gateway 192.168.0.1::redirect completed successfully::YES
+alice::swanctl --redirect --peer-id dave at strongswan.org --gateway moon.strongswan.org::redirect completed successfully::YES
+carol::sleep 1::No output expected::NO
+carol::cat /var/log/daemon.log::redirected to 192.168.0.1::YES
+dave::cat /var/log/daemon.log::redirected to moon.strongswan.org::YES
+moon::cat /var/log/daemon.log::client got redirected from 192.168.0.5::YES
+moon::ipsec status 2> /dev/null::rw\[1].*ESTABLISHED.*mars.strongswan.org.*carol at strongswan.org::YES
+moon::ipsec status 2> /dev/null::rw\[2].*ESTABLISHED.*mars.strongswan.org.*dave at strongswan.org::YES
+carol::ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
+dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
+carol::tcpdump::IP carol.strongswan.org > mars.strongswan.org: ESP::YES
+carol::tcpdump::IP mars.strongswan.org > carol.strongswan.org: ESP::NO
+carol::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
+carol::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
+dave::tcpdump::IP dave.strongswan.org > mars.strongswan.org: ESP::YES
+dave::tcpdump::IP mars.strongswan.org > dave.strongswan.org: ESP::NO
+dave::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
+dave::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES
+venus::tcpdump::IP carol.strongswan.org > venus.strongswan.org: ICMP echo request::YES
+venus::tcpdump::IP venus.strongswan.org > carol.strongswan.org: ICMP echo reply::YES
+venus::tcpdump::IP dave.strongswan.org > venus.strongswan.org: ICMP echo request::YES
+venus::tcpdump::IP venus.strongswan.org > dave.strongswan.org: ICMP echo reply::YES
diff --git a/testing/tests/ikev2/redirect-active/hosts/alice/etc/ipsec.conf b/testing/tests/ikev2/redirect-active/hosts/alice/etc/ipsec.conf
new file mode 100644
index 0000000..6a81055
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/hosts/alice/etc/ipsec.conf
@@ -0,0 +1,19 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+
+conn %default
+	ikelifetime=60m
+	keylife=20m
+	rekeymargin=3m
+	keyingtries=1
+
+conn rw
+	left=192.168.0.5
+	leftcert=marsCert.pem
+	leftid=mars.strongswan.org
+	leftsubnet=10.1.0.0/16
+	leftfirewall=yes
+	right=%any
+	keyexchange=ikev2
+	auto=add
diff --git a/testing/tests/ikev2/redirect-active/hosts/alice/etc/ipsec.d/certs/marsCert.pem b/testing/tests/ikev2/redirect-active/hosts/alice/etc/ipsec.d/certs/marsCert.pem
new file mode 100644
index 0000000..cf09774
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/hosts/alice/etc/ipsec.d/certs/marsCert.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEQDCCAyigAwIBAgIBNDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJDSDEZ
+MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBS
+b290IENBMB4XDTE1MTEyNjA4MjQ1M1oXDTE5MDkwNjA4MjQ1M1owZDELMAkGA1UE
+BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xHDAaBgNVBAsTE1ZpcnR1
+YWwgVlBOIEdhdGV3YXkxHDAaBgNVBAMTE21hcnMuc3Ryb25nc3dhbi5vcmcwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxTvcinIErfzu8YZKl+a2MNTVY
++qjG83OkweWjWed/egAugxRjTyWeKjrSNf6DWpXC0pNhzja+Sj0njz4Kq8VczkFB
+/yYEkFKpdpFQHXvbQo5h7wn1i3Omhvou5x0rRfddRpLGl7Z/Xg8gnHsZMHHN60hI
+qiLZdRSu5QF25WNcy9tO58gz8Hvo5jsk8YDu6eGYolaygQo3cqxx/r8yWzehju0F
+oWm4sLOrq+OTegeCQYI8PsOALAwLWgWdGfMPMT0ntq9tD97AcUD0EilvcXVdmwUW
+44/hM9BZ0JS7N7Wv6fgIChC7xhZj1yo6vY+FDsmNMhz7vdeulKx2dqRJkn0XAgMB
+AAGjggEaMIIBFjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIDqDAdBgNVHQ4EFgQUvo44
+06FQwLI8P6VqNehTNHa2LNMwbQYDVR0jBGYwZIAUXafdcAZRMn7ntm2zteXgYOou
+Te+hSaRHMEUxCzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2Fu
+MRswGQYDVQQDExJzdHJvbmdTd2FuIFJvb3QgQ0GCAQAwHgYDVR0RBBcwFYITbWFy
+cy5zdHJvbmdzd2FuLm9yZzATBgNVHSUEDDAKBggrBgEFBQcDATA5BgNVHR8EMjAw
+MC6gLKAqhihodHRwOi8vY3JsLnN0cm9uZ3N3YW4ub3JnL3N0cm9uZ3N3YW4uY3Js
+MA0GCSqGSIb3DQEBCwUAA4IBAQCWvHc0v5BhxsLRxPvcOu1bVoeexzA/5nftfRly
+PumU2hYFQ8p7soJiT/jYPmnfNvl6halnmS0FrqLdTMNfXj/6WCZ3w4Xnokc5PYW4
+oL1VqdEgR7jyQjifZuzRkuPw+yAFoT+HbMttLdRMVTq9NXlPXtGaJTWbx5Z/gGP3
+1Ry47WhvzJyRSysPh/+9WJFOwS6nf6DFbNuyVtNXQRzXjpsGefZgN9ysntNRFMMZ
+V0j+zFIkLBLh2WBkJsuLQM9EFAlZrpQZ7iwHuz7gU0jATxN6Qxnn9AemNPl4k8T3
+igPXeVhDbZFeTc+u/Z7X5i1HXhks2QGz/zGee6no54XOnBWB
+-----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/redirect-active/hosts/alice/etc/ipsec.d/private/marsKey.pem b/testing/tests/ikev2/redirect-active/hosts/alice/etc/ipsec.d/private/marsKey.pem
new file mode 100644
index 0000000..14f9440
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/hosts/alice/etc/ipsec.d/private/marsKey.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAsU73IpyBK387vGGSpfmtjDU1WPqoxvNzpMHlo1nnf3oALoMU
+Y08lnio60jX+g1qVwtKTYc42vko9J48+CqvFXM5BQf8mBJBSqXaRUB1720KOYe8J
+9Ytzpob6LucdK0X3XUaSxpe2f14PIJx7GTBxzetISKoi2XUUruUBduVjXMvbTufI
+M/B76OY7JPGA7unhmKJWsoEKN3Kscf6/Mls3oY7tBaFpuLCzq6vjk3oHgkGCPD7D
+gCwMC1oFnRnzDzE9J7avbQ/ewHFA9BIpb3F1XZsFFuOP4TPQWdCUuze1r+n4CAoQ
+u8YWY9cqOr2PhQ7JjTIc+73XrpSsdnakSZJ9FwIDAQABAoIBAQCe+TYMClamMUXV
++YYK2noIJAzY4qVA/DbLmi3S8GDnovNWwKAfCm+oCCUFJPQ1wZpVO4h5QPNEWjvK
+pFv0JV6nfyZzjdkAboYu+uf+9PB//oS6uiAr0AS5YnweYYl9qxXGw+gFtzEhsavO
+iX61bwIapsIApMrqPld1GE7f03vrTjyqYeJC+V5WEVZe1fkZtKFFJiHN1boPwoWt
+VRQ4UGlq9eto5pddmMcPl/uR9/TItdMC8AZ7fcRYP9RdYFEp8jS+tx3CDNs0XrlF
+qKlroDSdwBt475Ud5irtNwjGoohl3xCHvEne9l+fjlmQFynfRNeOb9rgVIsT3OoO
+MFSeW9HBAoGBAOiAjYCWoQHSlbi3Nkd5fsfTd4iZOkeeZi+2PJOhDByH1Hsq87CP
+KoYejjYUQ6QvJY2WDJCU8qXxPJkDuI6XZ6QbTDPad2xXDkA4pxuPi/c+Hb/eqLQ+
+24ebIzauC5iLdddp22oQXQOngKwUMihYggKs9cIpem8G99bcMfq1OeaDAoGBAMM6
+Z790eySPDIaKZZ/KVOu4hJe1s5vIJqN9xtV0o55PTR2wFCgwCogiXQchyhF8Qo6q
+BEpcKpY1bAivmL8T2PBsLUuKC4LAr8uzW8rVFbG3HfC62RoaVOZWmH+yBABi6eej
+Lh8KNhal+HzVOlMsw78FAkhq9aubWBywxfULFyrdAoGAPmnsEn3dIPkf+iMsrgk+
+cHQjHYdMrtclxV8daeAMuUf5UUsZeeck2jYvpPLRqayCXzzNiK6DaOqWgtkN3TFl
+wBcX4L+f2XSRPco3id2CDFAfeldSYHiTRBbwYAhe0od1jes73IAiCA4aK5eMU2pX
+FFLL8mBiHpX3SDV6MTwfG/MCgYEApgLXUC3LvVXLL+kl65ARUHUSgzNmrNSxTptY
+5hCORcNnbxRYv6fCfOrDspngC6hfrJMUnOrs59g7qtMvD2TgN+m1RqP3j9Msagp1
+xvAVx45QbnFkxdaYVVpTyVpmHrH99xSC1rBHOFEgEX78XtgVCC1JOK2DhM7PSW5k
+lzA8Hh0CgYBVXNnQsy4x+9D09zeFP2TKXsk7N154yUP6oxXu6OjZC+cfxHOGyi/g
+PVe8ukBIknZkFRz+ZXdfZzXXuJslENOVeFEInqVAu2W55KeCPc/3SU6hB2lj6MBl
+WIZ7yrUmtdalU3cPkFnHkQTL2glYAzjB2z22AxyXNzy37ZhtFpovtg==
+-----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/redirect-active/hosts/alice/etc/ipsec.secrets b/testing/tests/ikev2/redirect-active/hosts/alice/etc/ipsec.secrets
new file mode 100644
index 0000000..d65b96e
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/hosts/alice/etc/ipsec.secrets
@@ -0,0 +1,3 @@
+# /etc/ipsec.secrets - strongSwan IPsec secrets file
+
+: RSA marsKey.pem
diff --git a/testing/tests/ikev2/redirect-active/hosts/alice/etc/iptables.rules b/testing/tests/ikev2/redirect-active/hosts/alice/etc/iptables.rules
new file mode 100644
index 0000000..33c22b9
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/hosts/alice/etc/iptables.rules
@@ -0,0 +1,34 @@
+*filter
+
+# default policy is DROP
+-P INPUT DROP
+-P OUTPUT DROP
+-P FORWARD DROP
+
+# forward ESP-tunneled traffic
+-A FORWARD -i eth1 -m policy --dir in  --pol ipsec --proto esp -s PH_IP_CAROL -j ACCEPT
+-A FORWARD -i eth1 -m policy --dir in  --pol ipsec --proto esp -s PH_IP_DAVE  -j ACCEPT
+-A FORWARD -o eth1 -m policy --dir out --pol ipsec --proto esp -j ACCEPT
+
+# allow esp
+-A INPUT  -p 50 -j ACCEPT
+-A OUTPUT -p 50 -d PH_IP_CAROL -j ACCEPT
+-A OUTPUT -p 50 -d PH_IP_DAVE -j ACCEPT
+
+# allow IKE
+-A INPUT  -i eth1 -p udp --sport 500 --dport 500 -j ACCEPT
+-A OUTPUT -o eth1 -p udp --dport 500 --sport 500 -j ACCEPT
+
+# allow MobIKE
+-A INPUT  -i eth1 -p udp --sport 4500 --dport 4500 -j ACCEPT
+-A OUTPUT -o eth1 -p udp --dport 4500 --sport 4500 -j ACCEPT
+
+# allow crl fetch from winnetou
+-A INPUT  -i eth1 -p tcp --sport 80 -s PH_IP_WINNETOU -j ACCEPT
+-A OUTPUT -o eth1 -p tcp --dport 80 -d PH_IP_WINNETOU -j ACCEPT
+
+# allow ssh
+-A INPUT  -p tcp --dport 22 -j ACCEPT
+-A OUTPUT -p tcp --sport 22 -j ACCEPT
+
+COMMIT
diff --git a/testing/tests/ikev2/redirect-active/hosts/alice/etc/strongswan.conf b/testing/tests/ikev2/redirect-active/hosts/alice/etc/strongswan.conf
new file mode 100644
index 0000000..6f7f4c4
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/hosts/alice/etc/strongswan.conf
@@ -0,0 +1,6 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown vici
+}
+
diff --git a/testing/tests/ikev2/redirect-active/hosts/carol/etc/ipsec.conf b/testing/tests/ikev2/redirect-active/hosts/carol/etc/ipsec.conf
new file mode 100644
index 0000000..a5c2cc5
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/hosts/carol/etc/ipsec.conf
@@ -0,0 +1,19 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+	charondebug="knl 2"
+conn %default
+	ikelifetime=60m
+	keylife=20m
+	rekeymargin=3m
+	keyingtries=1
+
+conn home
+	leftcert=carolCert.pem
+	leftid=carol at strongswan.org
+	leftfirewall=yes
+	right=192.168.0.5
+	rightid=mars.strongswan.org
+	rightsubnet=10.1.0.0/16
+	keyexchange=ikev2
+	auto=add
diff --git a/testing/tests/ikev2/redirect-active/hosts/carol/etc/strongswan.conf b/testing/tests/ikev2/redirect-active/hosts/carol/etc/strongswan.conf
new file mode 100644
index 0000000..e58af9e
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,5 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac xcbc ctr ccm gcm stroke kernel-netlink socket-default updown
+}
diff --git a/testing/tests/ikev2/redirect-active/hosts/dave/etc/ipsec.conf b/testing/tests/ikev2/redirect-active/hosts/dave/etc/ipsec.conf
new file mode 100644
index 0000000..642811d
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/hosts/dave/etc/ipsec.conf
@@ -0,0 +1,19 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+
+conn %default
+	ikelifetime=60m
+	keylife=20m
+	rekeymargin=3m
+	keyingtries=1
+
+conn home
+	leftcert=daveCert.pem
+	leftid=dave at strongswan.org
+	leftfirewall=yes
+	right=192.168.0.5
+	rightid=mars.strongswan.org
+	rightsubnet=10.1.0.0/16
+	keyexchange=ikev2
+	auto=add
diff --git a/testing/tests/ikev2/redirect-active/hosts/dave/etc/strongswan.conf b/testing/tests/ikev2/redirect-active/hosts/dave/etc/strongswan.conf
new file mode 100644
index 0000000..ecbad66
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,6 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac xcbc ctr ccm gcm stroke kernel-netlink socket-default updown
+}
+
diff --git a/testing/tests/ikev2/redirect-active/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/redirect-active/hosts/moon/etc/ipsec.conf
new file mode 100644
index 0000000..fa901cb
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/hosts/moon/etc/ipsec.conf
@@ -0,0 +1,18 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+
+conn %default
+	ikelifetime=60m
+	keylife=20m
+	rekeymargin=3m
+	keyingtries=1
+
+conn rw
+	leftcert=marsCert.pem
+	leftid=mars.strongswan.org
+	leftsubnet=10.1.0.0/16
+	leftfirewall=yes
+	right=%any
+	keyexchange=ikev2
+	auto=add
diff --git a/testing/tests/ikev2/redirect-active/hosts/moon/etc/ipsec.d/certs/marsCert.pem b/testing/tests/ikev2/redirect-active/hosts/moon/etc/ipsec.d/certs/marsCert.pem
new file mode 100644
index 0000000..cf09774
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/hosts/moon/etc/ipsec.d/certs/marsCert.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEQDCCAyigAwIBAgIBNDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJDSDEZ
+MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBS
+b290IENBMB4XDTE1MTEyNjA4MjQ1M1oXDTE5MDkwNjA4MjQ1M1owZDELMAkGA1UE
+BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xHDAaBgNVBAsTE1ZpcnR1
+YWwgVlBOIEdhdGV3YXkxHDAaBgNVBAMTE21hcnMuc3Ryb25nc3dhbi5vcmcwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxTvcinIErfzu8YZKl+a2MNTVY
++qjG83OkweWjWed/egAugxRjTyWeKjrSNf6DWpXC0pNhzja+Sj0njz4Kq8VczkFB
+/yYEkFKpdpFQHXvbQo5h7wn1i3Omhvou5x0rRfddRpLGl7Z/Xg8gnHsZMHHN60hI
+qiLZdRSu5QF25WNcy9tO58gz8Hvo5jsk8YDu6eGYolaygQo3cqxx/r8yWzehju0F
+oWm4sLOrq+OTegeCQYI8PsOALAwLWgWdGfMPMT0ntq9tD97AcUD0EilvcXVdmwUW
+44/hM9BZ0JS7N7Wv6fgIChC7xhZj1yo6vY+FDsmNMhz7vdeulKx2dqRJkn0XAgMB
+AAGjggEaMIIBFjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIDqDAdBgNVHQ4EFgQUvo44
+06FQwLI8P6VqNehTNHa2LNMwbQYDVR0jBGYwZIAUXafdcAZRMn7ntm2zteXgYOou
+Te+hSaRHMEUxCzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2Fu
+MRswGQYDVQQDExJzdHJvbmdTd2FuIFJvb3QgQ0GCAQAwHgYDVR0RBBcwFYITbWFy
+cy5zdHJvbmdzd2FuLm9yZzATBgNVHSUEDDAKBggrBgEFBQcDATA5BgNVHR8EMjAw
+MC6gLKAqhihodHRwOi8vY3JsLnN0cm9uZ3N3YW4ub3JnL3N0cm9uZ3N3YW4uY3Js
+MA0GCSqGSIb3DQEBCwUAA4IBAQCWvHc0v5BhxsLRxPvcOu1bVoeexzA/5nftfRly
+PumU2hYFQ8p7soJiT/jYPmnfNvl6halnmS0FrqLdTMNfXj/6WCZ3w4Xnokc5PYW4
+oL1VqdEgR7jyQjifZuzRkuPw+yAFoT+HbMttLdRMVTq9NXlPXtGaJTWbx5Z/gGP3
+1Ry47WhvzJyRSysPh/+9WJFOwS6nf6DFbNuyVtNXQRzXjpsGefZgN9ysntNRFMMZ
+V0j+zFIkLBLh2WBkJsuLQM9EFAlZrpQZ7iwHuz7gU0jATxN6Qxnn9AemNPl4k8T3
+igPXeVhDbZFeTc+u/Z7X5i1HXhks2QGz/zGee6no54XOnBWB
+-----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/redirect-active/hosts/moon/etc/ipsec.d/private/marsKey.pem b/testing/tests/ikev2/redirect-active/hosts/moon/etc/ipsec.d/private/marsKey.pem
new file mode 100644
index 0000000..14f9440
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/hosts/moon/etc/ipsec.d/private/marsKey.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAsU73IpyBK387vGGSpfmtjDU1WPqoxvNzpMHlo1nnf3oALoMU
+Y08lnio60jX+g1qVwtKTYc42vko9J48+CqvFXM5BQf8mBJBSqXaRUB1720KOYe8J
+9Ytzpob6LucdK0X3XUaSxpe2f14PIJx7GTBxzetISKoi2XUUruUBduVjXMvbTufI
+M/B76OY7JPGA7unhmKJWsoEKN3Kscf6/Mls3oY7tBaFpuLCzq6vjk3oHgkGCPD7D
+gCwMC1oFnRnzDzE9J7avbQ/ewHFA9BIpb3F1XZsFFuOP4TPQWdCUuze1r+n4CAoQ
+u8YWY9cqOr2PhQ7JjTIc+73XrpSsdnakSZJ9FwIDAQABAoIBAQCe+TYMClamMUXV
++YYK2noIJAzY4qVA/DbLmi3S8GDnovNWwKAfCm+oCCUFJPQ1wZpVO4h5QPNEWjvK
+pFv0JV6nfyZzjdkAboYu+uf+9PB//oS6uiAr0AS5YnweYYl9qxXGw+gFtzEhsavO
+iX61bwIapsIApMrqPld1GE7f03vrTjyqYeJC+V5WEVZe1fkZtKFFJiHN1boPwoWt
+VRQ4UGlq9eto5pddmMcPl/uR9/TItdMC8AZ7fcRYP9RdYFEp8jS+tx3CDNs0XrlF
+qKlroDSdwBt475Ud5irtNwjGoohl3xCHvEne9l+fjlmQFynfRNeOb9rgVIsT3OoO
+MFSeW9HBAoGBAOiAjYCWoQHSlbi3Nkd5fsfTd4iZOkeeZi+2PJOhDByH1Hsq87CP
+KoYejjYUQ6QvJY2WDJCU8qXxPJkDuI6XZ6QbTDPad2xXDkA4pxuPi/c+Hb/eqLQ+
+24ebIzauC5iLdddp22oQXQOngKwUMihYggKs9cIpem8G99bcMfq1OeaDAoGBAMM6
+Z790eySPDIaKZZ/KVOu4hJe1s5vIJqN9xtV0o55PTR2wFCgwCogiXQchyhF8Qo6q
+BEpcKpY1bAivmL8T2PBsLUuKC4LAr8uzW8rVFbG3HfC62RoaVOZWmH+yBABi6eej
+Lh8KNhal+HzVOlMsw78FAkhq9aubWBywxfULFyrdAoGAPmnsEn3dIPkf+iMsrgk+
+cHQjHYdMrtclxV8daeAMuUf5UUsZeeck2jYvpPLRqayCXzzNiK6DaOqWgtkN3TFl
+wBcX4L+f2XSRPco3id2CDFAfeldSYHiTRBbwYAhe0od1jes73IAiCA4aK5eMU2pX
+FFLL8mBiHpX3SDV6MTwfG/MCgYEApgLXUC3LvVXLL+kl65ARUHUSgzNmrNSxTptY
+5hCORcNnbxRYv6fCfOrDspngC6hfrJMUnOrs59g7qtMvD2TgN+m1RqP3j9Msagp1
+xvAVx45QbnFkxdaYVVpTyVpmHrH99xSC1rBHOFEgEX78XtgVCC1JOK2DhM7PSW5k
+lzA8Hh0CgYBVXNnQsy4x+9D09zeFP2TKXsk7N154yUP6oxXu6OjZC+cfxHOGyi/g
+PVe8ukBIknZkFRz+ZXdfZzXXuJslENOVeFEInqVAu2W55KeCPc/3SU6hB2lj6MBl
+WIZ7yrUmtdalU3cPkFnHkQTL2glYAzjB2z22AxyXNzy37ZhtFpovtg==
+-----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/redirect-active/hosts/moon/etc/ipsec.secrets b/testing/tests/ikev2/redirect-active/hosts/moon/etc/ipsec.secrets
new file mode 100644
index 0000000..d65b96e
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/hosts/moon/etc/ipsec.secrets
@@ -0,0 +1,3 @@
+# /etc/ipsec.secrets - strongSwan IPsec secrets file
+
+: RSA marsKey.pem
diff --git a/testing/tests/ikev2/redirect-active/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/redirect-active/hosts/moon/etc/strongswan.conf
new file mode 100644
index 0000000..7c415b1
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,6 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown
+}
+
diff --git a/testing/tests/ikev2/redirect-active/posttest.dat b/testing/tests/ikev2/redirect-active/posttest.dat
new file mode 100644
index 0000000..7e436a6
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/posttest.dat
@@ -0,0 +1,10 @@
+carol::ipsec stop
+dave::ipsec stop
+moon::ipsec stop
+alice::ipsec stop
+moon::iptables-restore < /etc/iptables.flush
+alice::iptables-restore < /etc/iptables.flush
+carol::iptables-restore < /etc/iptables.flush
+dave::iptables-restore < /etc/iptables.flush
+alice::ip addr del 192.168.0.5/24 dev eth1
+alice::ifdown eth1
diff --git a/testing/tests/ikev2/redirect-active/pretest.dat b/testing/tests/ikev2/redirect-active/pretest.dat
new file mode 100644
index 0000000..3f7ac1d
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/pretest.dat
@@ -0,0 +1,13 @@
+alice::ifup eth1
+alice::ip addr add 192.168.0.5/24 dev eth1
+moon::iptables-restore < /etc/iptables.rules
+alice::iptables-restore < /etc/iptables.rules
+carol::iptables-restore < /etc/iptables.rules
+dave::iptables-restore < /etc/iptables.rules
+moon::ipsec start
+alice::ipsec start
+carol::ipsec start
+dave::ipsec start
+carol::sleep 1
+carol::ipsec up home
+dave::ipsec up home
diff --git a/testing/tests/ikev2/redirect-active/test.conf b/testing/tests/ikev2/redirect-active/test.conf
new file mode 100644
index 0000000..8056d9c
--- /dev/null
+++ b/testing/tests/ikev2/redirect-active/test.conf
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# guest instances used for this test
+
+# All guest instances that are required for this test
+#
+VIRTHOSTS="alice venus moon carol winnetou dave"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-v-m-c-w-d.png"
+
+# Guest instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="venus carol dave"
+
+# Guest instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="alice moon carol dave"
diff --git a/testing/tests/ikev2/rw-dnssec/pretest.dat b/testing/tests/ikev2/rw-dnssec/pretest.dat
index e827687..ab5e18d 100644
--- a/testing/tests/ikev2/rw-dnssec/pretest.dat
+++ b/testing/tests/ikev2/rw-dnssec/pretest.dat
@@ -4,9 +4,9 @@ dave::iptables-restore < /etc/iptables.rules
 moon::rm /etc/ipsec.d/cacerts/*
 carol::rm /etc/ipsec.d/cacerts/*
 dave::rm /etc/ipsec.d/cacerts/*
+moon::ipsec start
 carol::ipsec start
 dave::ipsec start
-moon::ipsec start
 carol::expect-connection home
 carol::ipsec up home
 dave::expect-connection home
diff --git a/testing/tests/ikev2/trap-any/evaltest.dat b/testing/tests/ikev2/trap-any/evaltest.dat
index b62e890..27df31f 100644
--- a/testing/tests/ikev2/trap-any/evaltest.dat
+++ b/testing/tests/ikev2/trap-any/evaltest.dat
@@ -1,8 +1,8 @@
-moon::ping -c 2 -W 1 -i 0.2 PH_IP_SUN::64 bytes from PH_IP_SUN: icmp_req=2::YES
-moon::ping -c 2 -W 1 -i 0.2 PH_IP_CAROL::64 bytes from PH_IP_CAROL: icmp_req=2::YES
-sun::ping -c 2 -W 1 -i 0.2 PH_IP_CAROL::64 bytes from PH_IP_CAROL: icmp_req=2::YES
-dave::ping -c 2 -W 1 -i 0.2 PH_IP_MOON::64 bytes from PH_IP_MOON: icmp_req=2::YES
-dave::ping -c 2 -W 1 -i 0.2 PH_IP_SUN::64 bytes from PH_IP_SUN: icmp_req=2::YES
+moon::ping -c 2 -W 1 -i 0.4 PH_IP_SUN::64 bytes from PH_IP_SUN: icmp_req=2::YES
+moon::ping -c 2 -W 1 -i 0.4 PH_IP_CAROL::64 bytes from PH_IP_CAROL: icmp_req=2::YES
+sun::ping -c 2 -W 1 -i 0.4 PH_IP_CAROL::64 bytes from PH_IP_CAROL: icmp_req=2::YES
+dave::ping -c 2 -W 1 -i 0.4 PH_IP_MOON::64 bytes from PH_IP_MOON: icmp_req=2::YES
+dave::ping -c 2 -W 1 -i 0.4 PH_IP_SUN::64 bytes from PH_IP_SUN: icmp_req=2::YES
 dave::ping -c 1 PH_IP_CAROL::64 bytes from PH_IP_CAROL: icmp_req=1::YES
 moon::ipsec status 2> /dev/null::trap-any.*ESTABLISHED.*PH_IP_MOON.*PH_IP_SUN::YES
 moon::ipsec status 2> /dev/null::trap-any.*ESTABLISHED.*PH_IP_MOON.*PH_IP_CAROL::YES
diff --git a/testing/tests/libipsec/net2net-null/evaltest.dat b/testing/tests/libipsec/net2net-null/evaltest.dat
index e455a36..0cafb4f 100644
--- a/testing/tests/libipsec/net2net-null/evaltest.dat
+++ b/testing/tests/libipsec/net2net-null/evaltest.dat
@@ -2,8 +2,8 @@ moon::ipsec status 2> /dev/null::net-net.*ESTABLISHED.*moon.strongswan.org.*sun.
 sun:: ipsec status 2> /dev/null::net-net.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES
 moon::ipsec status 2> /dev/null::net-net.*INSTALLED, TUNNEL::YES
 sun:: ipsec status 2> /dev/null::net-net.*INSTALLED, TUNNEL::YES
-moon::ipsec statusall 2> /dev/null::net-net\[1].*NULL/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048::YES
-sun:: ipsec statusall 2> /dev/null::net-net\[1].*NULL/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048::YES
+moon::ipsec statusall 2> /dev/null::net-net\[1].*NULL/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072::YES
+sun:: ipsec statusall 2> /dev/null::net-net\[1].*NULL/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072::YES
 alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
 moon::ipsec statusall 2> /dev/null::net-net[{]1}.*NULL/HMAC_SHA2_256::YES
 sun:: ipsec statusall 2> /dev/null::net-net[{]1}.*NULL/HMAC_SHA2_256::YES
diff --git a/testing/tests/libipsec/net2net-null/hosts/moon/etc/ipsec.conf b/testing/tests/libipsec/net2net-null/hosts/moon/etc/ipsec.conf
index 4ecfb0e..f206a16 100644
--- a/testing/tests/libipsec/net2net-null/hosts/moon/etc/ipsec.conf
+++ b/testing/tests/libipsec/net2net-null/hosts/moon/etc/ipsec.conf
@@ -8,8 +8,8 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev2
-	ike=null-sha256-modp2048!
-	esp=null-sha256-modp2048!
+	ike=null-sha256-modp3072!
+	esp=null-sha256-modp3072!
 	mobike=no
 
 conn net-net
diff --git a/testing/tests/libipsec/net2net-null/hosts/sun/etc/ipsec.conf b/testing/tests/libipsec/net2net-null/hosts/sun/etc/ipsec.conf
index 95ea20d..21b1165 100644
--- a/testing/tests/libipsec/net2net-null/hosts/sun/etc/ipsec.conf
+++ b/testing/tests/libipsec/net2net-null/hosts/sun/etc/ipsec.conf
@@ -8,8 +8,8 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev2
-	ike=null-sha256-modp2048!
-	esp=null-sha256-modp2048!
+	ike=null-sha256-modp3072!
+	esp=null-sha256-modp3072!
 	mobike=no
 
 conn net-net
diff --git a/testing/tests/openssl-ikev1/alg-camellia/evaltest.dat b/testing/tests/openssl-ikev1/alg-camellia/evaltest.dat
index 4d614bf..3b67703 100644
--- a/testing/tests/openssl-ikev1/alg-camellia/evaltest.dat
+++ b/testing/tests/openssl-ikev1/alg-camellia/evaltest.dat
@@ -1,11 +1,11 @@
 carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
 moon:: ipsec status 2> /dev/null::rw.*INSTALLED, TUNNEL::YES
-moon:: ipsec statusall 2> /dev/null::IKE proposal: CAMELLIA_CBC_256/HMAC_SHA2_512_256/PRF_HMAC_SHA2_512/MODP_2048::YES
-carol::ipsec statusall 2> /dev/null::IKE proposal: CAMELLIA_CBC_256/HMAC_SHA2_512_256/PRF_HMAC_SHA2_512/MODP_2048::YES
+moon:: ipsec statusall 2> /dev/null::IKE proposal: CAMELLIA_CBC_256/HMAC_SHA2_512_256/PRF_HMAC_SHA2_512/MODP_3072::YES
+carol::ipsec statusall 2> /dev/null::IKE proposal: CAMELLIA_CBC_256/HMAC_SHA2_512_256/PRF_HMAC_SHA2_512/MODP_3072::YES
 carol::ping -c 1 -s 120 -p deadbeef PH_IP_ALICE::128 bytes from PH_IP_ALICE: icmp_req=1::YES
-moon:: ipsec statusall 2> /dev/null::CAMELLIA_CBC_192/HMAC_SHA1_96::YES
-carol::ipsec statusall 2> /dev/null::CAMELLIA_CBC_192/HMAC_SHA1_96::YES
+moon:: ipsec statusall 2> /dev/null::CAMELLIA_CBC_192/HMAC_SHA2_384_192::YES
+carol::ipsec statusall 2> /dev/null::CAMELLIA_CBC_192/HMAC_SHA2_384_192::YES
 moon:: ip xfrm state::enc cbc(camellia)::YES
 carol::ip xfrm state::enc cbc(camellia)::YES
-moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP.*length 196::YES
-moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP.*length 196::YES
+moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP.*length 208::YES
+moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP.*length 208::YES
diff --git a/testing/tests/openssl-ikev1/alg-camellia/hosts/carol/etc/ipsec.conf b/testing/tests/openssl-ikev1/alg-camellia/hosts/carol/etc/ipsec.conf
index 7a27680..4628311 100644
--- a/testing/tests/openssl-ikev1/alg-camellia/hosts/carol/etc/ipsec.conf
+++ b/testing/tests/openssl-ikev1/alg-camellia/hosts/carol/etc/ipsec.conf
@@ -8,8 +8,8 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev1
-	ike=camellia256-sha512-modp2048!
-	esp=camellia192-sha1!
+	ike=camellia256-sha512-modp3072!
+	esp=camellia192-sha384!
 
 conn home
 	left=PH_IP_CAROL
diff --git a/testing/tests/openssl-ikev1/alg-camellia/hosts/moon/etc/ipsec.conf b/testing/tests/openssl-ikev1/alg-camellia/hosts/moon/etc/ipsec.conf
index fb892a0..da1fbf0 100644
--- a/testing/tests/openssl-ikev1/alg-camellia/hosts/moon/etc/ipsec.conf
+++ b/testing/tests/openssl-ikev1/alg-camellia/hosts/moon/etc/ipsec.conf
@@ -8,8 +8,8 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev1
-	ike=camellia256-sha512-modp2048!
-	esp=camellia192-sha1!
+	ike=camellia256-sha512-modp3072!
+	esp=camellia192-sha384!
 
 conn rw
 	left=PH_IP_MOON
diff --git a/testing/tests/openssl-ikev1/ecdsa-certs/evaltest.dat b/testing/tests/openssl-ikev1/ecdsa-certs/evaltest.dat
index 69c893f..941a2fe 100644
--- a/testing/tests/openssl-ikev1/ecdsa-certs/evaltest.dat
+++ b/testing/tests/openssl-ikev1/ecdsa-certs/evaltest.dat
@@ -8,10 +8,10 @@ moon:: ipsec status 2> /dev/null::rw[{]1}.*INSTALLED, TUNNEL::YES
 moon:: ipsec status 2> /dev/null::rw[{]2}.*INSTALLED, TUNNEL::YES
 moon:: cat /var/log/daemon.log::looking for ECDSA-256 signature peer configs matching.*carol at strongswan.org::YES
 moon:: cat /var/log/daemon.log::looking for ECDSA-384 signature peer configs matching.*dave at strongswan.org::YES
-moon:: cat /var/log/daemon.log::authentication of.*carol at strongswan.org.*with ECDSA successful::YES
-moon:: cat /var/log/daemon.log::authentication of.*dave at strongswan.org.*with ECDSA successful::YES
-carol::cat /var/log/daemon.log::authentication of.*moon.strongswan.org.*with ECDSA successful::YES
-dave:: cat /var/log/daemon.log::authentication of.*moon.strongswan.org.*with ECDSA successful::YES
+moon:: cat /var/log/daemon.log::authentication of.*carol at strongswan.org.*with ECDSA_WITH_NULL successful::YES
+moon:: cat /var/log/daemon.log::authentication of.*dave at strongswan.org.*with ECDSA_WITH_NULL successful::YES
+carol::cat /var/log/daemon.log::authentication of.*moon.strongswan.org.*with ECDSA_WITH_NULL successful::YES
+dave:: cat /var/log/daemon.log::authentication of.*moon.strongswan.org.*with ECDSA_WITH_NULL successful::YES
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
 dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
 moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/openssl-ikev2/alg-camellia/evaltest.dat b/testing/tests/openssl-ikev2/alg-camellia/evaltest.dat
index 4d614bf..3b67703 100644
--- a/testing/tests/openssl-ikev2/alg-camellia/evaltest.dat
+++ b/testing/tests/openssl-ikev2/alg-camellia/evaltest.dat
@@ -1,11 +1,11 @@
 carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
 moon:: ipsec status 2> /dev/null::rw.*INSTALLED, TUNNEL::YES
-moon:: ipsec statusall 2> /dev/null::IKE proposal: CAMELLIA_CBC_256/HMAC_SHA2_512_256/PRF_HMAC_SHA2_512/MODP_2048::YES
-carol::ipsec statusall 2> /dev/null::IKE proposal: CAMELLIA_CBC_256/HMAC_SHA2_512_256/PRF_HMAC_SHA2_512/MODP_2048::YES
+moon:: ipsec statusall 2> /dev/null::IKE proposal: CAMELLIA_CBC_256/HMAC_SHA2_512_256/PRF_HMAC_SHA2_512/MODP_3072::YES
+carol::ipsec statusall 2> /dev/null::IKE proposal: CAMELLIA_CBC_256/HMAC_SHA2_512_256/PRF_HMAC_SHA2_512/MODP_3072::YES
 carol::ping -c 1 -s 120 -p deadbeef PH_IP_ALICE::128 bytes from PH_IP_ALICE: icmp_req=1::YES
-moon:: ipsec statusall 2> /dev/null::CAMELLIA_CBC_192/HMAC_SHA1_96::YES
-carol::ipsec statusall 2> /dev/null::CAMELLIA_CBC_192/HMAC_SHA1_96::YES
+moon:: ipsec statusall 2> /dev/null::CAMELLIA_CBC_192/HMAC_SHA2_384_192::YES
+carol::ipsec statusall 2> /dev/null::CAMELLIA_CBC_192/HMAC_SHA2_384_192::YES
 moon:: ip xfrm state::enc cbc(camellia)::YES
 carol::ip xfrm state::enc cbc(camellia)::YES
-moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP.*length 196::YES
-moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP.*length 196::YES
+moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP.*length 208::YES
+moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP.*length 208::YES
diff --git a/testing/tests/openssl-ikev2/alg-camellia/hosts/carol/etc/ipsec.conf b/testing/tests/openssl-ikev2/alg-camellia/hosts/carol/etc/ipsec.conf
index 0042954..f0bbfc1 100644
--- a/testing/tests/openssl-ikev2/alg-camellia/hosts/carol/etc/ipsec.conf
+++ b/testing/tests/openssl-ikev2/alg-camellia/hosts/carol/etc/ipsec.conf
@@ -8,8 +8,8 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev2
-	ike=camellia256-sha512-modp2048!
-	esp=camellia192-sha1!
+	ike=camellia256-sha512-modp3072!
+	esp=camellia192-sha384!
 
 conn home
 	left=PH_IP_CAROL
diff --git a/testing/tests/openssl-ikev2/alg-camellia/hosts/moon/etc/ipsec.conf b/testing/tests/openssl-ikev2/alg-camellia/hosts/moon/etc/ipsec.conf
index 0f6a4f5..8481f89 100644
--- a/testing/tests/openssl-ikev2/alg-camellia/hosts/moon/etc/ipsec.conf
+++ b/testing/tests/openssl-ikev2/alg-camellia/hosts/moon/etc/ipsec.conf
@@ -8,8 +8,8 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev2
-	ike=camellia256-sha512-modp2048!
-	esp=camellia192-sha1!
+	ike=camellia256-sha512-modp3072!
+	esp=camellia192-sha384!
 
 conn rw
 	left=PH_IP_MOON
diff --git a/testing/tests/pfkey/alg-aes-xcbc/evaltest.dat b/testing/tests/pfkey/alg-aes-xcbc/evaltest.dat
index 590b7fe..9c6b73b 100644
--- a/testing/tests/pfkey/alg-aes-xcbc/evaltest.dat
+++ b/testing/tests/pfkey/alg-aes-xcbc/evaltest.dat
@@ -2,8 +2,8 @@ moon:: ipsec status 2> /dev/null::rw.*ESTABLISHED.*moon.strongswan.org.*carol at st
 carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
 moon:: ipsec status 2> /dev/null::rw.*INSTALLED, TUNNEL::YES
 carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-moon:: ipsec statusall 2> /dev/null::rw.*IKE proposal.*AES_CBC_128/AES_XCBC_96/PRF_AES128_XCBC/MODP_2048::YES
-carol::ipsec statusall 2> /dev/null::home.*IKE proposal.*AES_CBC_128/AES_XCBC_96/PRF_AES128_XCBC/MODP_2048::YES
+moon:: ipsec statusall 2> /dev/null::rw.*IKE proposal.*AES_CBC_128/AES_XCBC_96/PRF_AES128_XCBC/MODP_3072::YES
+carol::ipsec statusall 2> /dev/null::home.*IKE proposal.*AES_CBC_128/AES_XCBC_96/PRF_AES128_XCBC/MODP_3072::YES
 carol::ping -c 1 -s 120 -p deadbeef PH_IP_ALICE::128 bytes from PH_IP_ALICE: icmp_req=1::YES
 moon:: ipsec statusall 2> /dev/null::rw.*AES_CBC_128/AES_XCBC_96,::YES
 carol::ipsec statusall 2> /dev/null::home.*AES_CBC_128/AES_XCBC_96,::YES
diff --git a/testing/tests/pfkey/alg-aes-xcbc/hosts/carol/etc/ipsec.conf b/testing/tests/pfkey/alg-aes-xcbc/hosts/carol/etc/ipsec.conf
index 74668e7..c9e9e92 100644
--- a/testing/tests/pfkey/alg-aes-xcbc/hosts/carol/etc/ipsec.conf
+++ b/testing/tests/pfkey/alg-aes-xcbc/hosts/carol/etc/ipsec.conf
@@ -8,8 +8,8 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev2
-	ike=aes128-aesxcbc-modp2048!
-	esp=aes128-aesxcbc-modp2048!
+	ike=aes128-aesxcbc-modp3072!
+	esp=aes128-aesxcbc-modp3072!
 
 conn home
 	left=PH_IP_CAROL
diff --git a/testing/tests/pfkey/alg-aes-xcbc/hosts/moon/etc/ipsec.conf b/testing/tests/pfkey/alg-aes-xcbc/hosts/moon/etc/ipsec.conf
index 3cda729..4e4a932 100644
--- a/testing/tests/pfkey/alg-aes-xcbc/hosts/moon/etc/ipsec.conf
+++ b/testing/tests/pfkey/alg-aes-xcbc/hosts/moon/etc/ipsec.conf
@@ -8,8 +8,8 @@ conn %default
 	rekeymargin=3m
 	keyingtries=1
 	keyexchange=ikev2
-	ike=aes128-aesxcbc-modp2048!
-	esp=aes128-aesxcbc-modp2048!
+	ike=aes128-aesxcbc-modp3072!
+	esp=aes128-aesxcbc-modp3072!
 
 conn rw
 	left=PH_IP_MOON
diff --git a/testing/tests/sql/ip-pool-db-expired/evaltest.dat b/testing/tests/sql/ip-pool-db-expired/evaltest.dat
index 5ff5edb..9b84561 100644
--- a/testing/tests/sql/ip-pool-db-expired/evaltest.dat
+++ b/testing/tests/sql/ip-pool-db-expired/evaltest.dat
@@ -1,25 +1,21 @@
 carol::cat /var/log/daemon.log::installing new virtual IP PH_IP_CAROL1::YES
 carol::ip addr list dev eth0::PH_IP_CAROL1::YES
 carol::ip route list table 220::10.1.0.0/16.*src PH_IP_CAROL1::YES
-carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
-carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.3.0.1] child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*lo [...]
 dave:: cat /var/log/daemon.log::installing new virtual IP PH_IP_DAVE1::YES
 dave:: ip addr list dev eth0::PH_IP_DAVE1::YES
 dave:: ip route list table 220::10.1.0.0/16.*src PH_IP_DAVE1::YES
-dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*dave at strongswan.org.*moon.strongswan.org::YES
-dave:: ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
 dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.3.0.2] child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*loc [...]
 moon:: cat /var/log/daemon.log::peer requested virtual IP %any::YES
 moon:: cat /var/log/daemon.log::acquired new lease for address.*in pool.*bigpool::YES
 moon:: cat /var/log/daemon.log::assigning virtual IP::YES
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.3.0.1] child-sas.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts [...]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.3.0.2] child-sas.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts= [...]
 moon:: ipsec pool --status 2> /dev/null::bigpool.*10.3.0.1.*10.3.0.6.*1h.*2::YES
 moon:: ipsec pool --leases --filter pool=bigpool,addr=10.3.0.1,id=carol at strongswan.org 2> /dev/null::online::YES
 moon:: ipsec pool --leases --filter pool=bigpool,addr=10.3.0.2,id=dave at strongswan.org 2> /dev/null::online::YES
-moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*carol at strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*dave at strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw[{]1}.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]2}.*INSTALLED, TUNNEL::YES
 moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
 moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
 moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/sql/ip-pool-db-expired/hosts/carol/etc/ipsec.d/data.sql b/testing/tests/sql/ip-pool-db-expired/hosts/carol/etc/ipsec.d/data.sql
index 4a5d349..d5c4452 100644
--- a/testing/tests/sql/ip-pool-db-expired/hosts/carol/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/ip-pool-db-expired/hosts/carol/etc/ipsec.d/data.sql
@@ -117,7 +117,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/ip-pool-db-expired/hosts/carol/etc/strongswan.conf b/testing/tests/sql/ip-pool-db-expired/hosts/carol/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/ip-pool-db-expired/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/sql/ip-pool-db-expired/hosts/carol/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/ip-pool-db-expired/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/sql/ip-pool-db-expired/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/ip-pool-db-expired/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/ip-pool-db-expired/hosts/dave/etc/ipsec.d/data.sql b/testing/tests/sql/ip-pool-db-expired/hosts/dave/etc/ipsec.d/data.sql
index 85e4752..a44dc27 100644
--- a/testing/tests/sql/ip-pool-db-expired/hosts/dave/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/ip-pool-db-expired/hosts/dave/etc/ipsec.d/data.sql
@@ -111,7 +111,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/ip-pool-db-expired/hosts/dave/etc/strongswan.conf b/testing/tests/sql/ip-pool-db-expired/hosts/dave/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/ip-pool-db-expired/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/sql/ip-pool-db-expired/hosts/dave/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/ip-pool-db-expired/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/sql/ip-pool-db-expired/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/ip-pool-db-expired/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/ip-pool-db-expired/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/ip-pool-db-expired/hosts/moon/etc/ipsec.d/data.sql
index a584dd8..315749b 100644
--- a/testing/tests/sql/ip-pool-db-expired/hosts/moon/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/ip-pool-db-expired/hosts/moon/etc/ipsec.d/data.sql
@@ -135,7 +135,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'rw', 'ipsec _updown iptables'
+  'rw', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/ip-pool-db-expired/hosts/moon/etc/strongswan.conf b/testing/tests/sql/ip-pool-db-expired/hosts/moon/etc/strongswan.conf
index 64e7cc7..2e9e646 100644
--- a/testing/tests/sql/ip-pool-db-expired/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/sql/ip-pool-db-expired/hosts/moon/etc/strongswan.conf
@@ -1,16 +1,12 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql attr-sql
+
   plugins {
     sql {
       database = sqlite:///etc/db.d/ipsec.db
     }
-  }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql attr-sql
-}
-
-libhydra {
-  plugins {
     attr-sql {
       database = sqlite:///etc/db.d/ipsec.db
     }
diff --git a/testing/tests/sql/ip-pool-db-expired/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/sql/ip-pool-db-expired/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/ip-pool-db-expired/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/ip-pool-db-expired/posttest.dat b/testing/tests/sql/ip-pool-db-expired/posttest.dat
index b757d8b..d7107cc 100644
--- a/testing/tests/sql/ip-pool-db-expired/posttest.dat
+++ b/testing/tests/sql/ip-pool-db-expired/posttest.dat
@@ -1,6 +1,8 @@
-carol::ipsec stop
-dave::ipsec stop
-moon::ipsec stop
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/sql/ip-pool-db-expired/pretest.dat b/testing/tests/sql/ip-pool-db-expired/pretest.dat
index 3e1b762..068d729 100644
--- a/testing/tests/sql/ip-pool-db-expired/pretest.dat
+++ b/testing/tests/sql/ip-pool-db-expired/pretest.dat
@@ -1,6 +1,3 @@
-moon::rm /etc/ipsec.d/cacerts/*
-carol::rm /etc/ipsec.d/cacerts/*
-dave::rm /etc/ipsec.d/cacerts/*
 moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 carol::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 dave::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
@@ -11,10 +8,11 @@ moon::ipsec pool --leases 2> /dev/null
 moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
 dave::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/sql/ip-pool-db-expired/test.conf b/testing/tests/sql/ip-pool-db-expired/test.conf
index 450100f..ae4f834 100644
--- a/testing/tests/sql/ip-pool-db-expired/test.conf
+++ b/testing/tests/sql/ip-pool-db-expired/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="moon carol dave"
 # Guest instances on which databases are used
 #
 DBHOSTS="$IPSECHOSTS"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/sql/ip-pool-db-restart/evaltest.dat b/testing/tests/sql/ip-pool-db-restart/evaltest.dat
index f70e2d2..ce7a8f5 100644
--- a/testing/tests/sql/ip-pool-db-restart/evaltest.dat
+++ b/testing/tests/sql/ip-pool-db-restart/evaltest.dat
@@ -1,25 +1,21 @@
 carol::cat /var/log/daemon.log::installing new virtual IP PH_IP_CAROL1::YES
 carol::ip addr list dev eth0::PH_IP_CAROL1::YES
 carol::ip route list table 220::10.1.0.0/16.*src PH_IP_CAROL1::YES
-carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
-carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.3.0.1] child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*lo [...]
 dave:: cat /var/log/daemon.log::installing new virtual IP PH_IP_DAVE1::YES
 dave:: ip addr list dev eth0::PH_IP_DAVE1::YES
 dave:: ip route list table 220::10.1.0.0/16.*src PH_IP_DAVE1::YES
-dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*dave at strongswan.org.*moon.strongswan.org::YES
-dave:: ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
 dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.3.0.2] child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*loc [...]
 moon:: cat /var/log/daemon.log::peer requested virtual IP %any::YES
 moon:: cat /var/log/daemon.log::acquired existing lease for address.*in pool.*bigpool::YES
 moon:: cat /var/log/daemon.log::assigning virtual IP::YES
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.3.0.1] child-sas.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts [...]
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.3.0.2] child-sas.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts= [...]
 moon:: ipsec pool --status 2> /dev/null::bigpool.*10.3.0.1.*10.3.0.6.*static.*2::YES
 moon:: ipsec pool --leases --filter pool=bigpool,addr=10.3.0.1,id=carol at strongswan.org 2> /dev/null::online::YES
 moon:: ipsec pool --leases --filter pool=bigpool,addr=10.3.0.2,id=dave at strongswan.org 2> /dev/null::online::YES
-moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*dave at strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*carol at strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw[{]1}.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]2}.*INSTALLED, TUNNEL::YES
 moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
 moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
 moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/sql/ip-pool-db-restart/hosts/carol/etc/ipsec.d/data.sql b/testing/tests/sql/ip-pool-db-restart/hosts/carol/etc/ipsec.d/data.sql
index 4a5d349..d5c4452 100644
--- a/testing/tests/sql/ip-pool-db-restart/hosts/carol/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/ip-pool-db-restart/hosts/carol/etc/ipsec.d/data.sql
@@ -117,7 +117,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/ip-pool-db-restart/hosts/carol/etc/strongswan.conf b/testing/tests/sql/ip-pool-db-restart/hosts/carol/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/ip-pool-db-restart/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/sql/ip-pool-db-restart/hosts/carol/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/ip-pool-db-restart/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/sql/ip-pool-db-restart/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/ip-pool-db-restart/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/ip-pool-db-restart/hosts/dave/etc/ipsec.d/data.sql b/testing/tests/sql/ip-pool-db-restart/hosts/dave/etc/ipsec.d/data.sql
index a832d06..6f2d0fc 100644
--- a/testing/tests/sql/ip-pool-db-restart/hosts/dave/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/ip-pool-db-restart/hosts/dave/etc/ipsec.d/data.sql
@@ -117,7 +117,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/ip-pool-db-restart/hosts/dave/etc/strongswan.conf b/testing/tests/sql/ip-pool-db-restart/hosts/dave/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/ip-pool-db-restart/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/sql/ip-pool-db-restart/hosts/dave/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/ip-pool-db-restart/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/sql/ip-pool-db-restart/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/ip-pool-db-restart/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/ip-pool-db-restart/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/ip-pool-db-restart/hosts/moon/etc/ipsec.d/data.sql
index 6e33e05..399de69 100644
--- a/testing/tests/sql/ip-pool-db-restart/hosts/moon/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/ip-pool-db-restart/hosts/moon/etc/ipsec.d/data.sql
@@ -129,7 +129,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'rw', 'ipsec _updown iptables'
+  'rw', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/ip-pool-db-restart/hosts/moon/etc/strongswan.conf b/testing/tests/sql/ip-pool-db-restart/hosts/moon/etc/strongswan.conf
index 64e7cc7..2e9e646 100644
--- a/testing/tests/sql/ip-pool-db-restart/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/sql/ip-pool-db-restart/hosts/moon/etc/strongswan.conf
@@ -1,16 +1,12 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql attr-sql
+
   plugins {
     sql {
       database = sqlite:///etc/db.d/ipsec.db
     }
-  }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql attr-sql
-}
-
-libhydra {
-  plugins {
     attr-sql {
       database = sqlite:///etc/db.d/ipsec.db
     }
diff --git a/testing/tests/sql/ip-pool-db-restart/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/sql/ip-pool-db-restart/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/ip-pool-db-restart/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/ip-pool-db-restart/posttest.dat b/testing/tests/sql/ip-pool-db-restart/posttest.dat
index b757d8b..d7107cc 100644
--- a/testing/tests/sql/ip-pool-db-restart/posttest.dat
+++ b/testing/tests/sql/ip-pool-db-restart/posttest.dat
@@ -1,6 +1,8 @@
-carol::ipsec stop
-dave::ipsec stop
-moon::ipsec stop
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/sql/ip-pool-db-restart/pretest.dat b/testing/tests/sql/ip-pool-db-restart/pretest.dat
index 4976693..374693e 100644
--- a/testing/tests/sql/ip-pool-db-restart/pretest.dat
+++ b/testing/tests/sql/ip-pool-db-restart/pretest.dat
@@ -1,6 +1,3 @@
-moon::rm /etc/ipsec.d/cacerts/*
-carol::rm /etc/ipsec.d/cacerts/*
-dave::rm /etc/ipsec.d/cacerts/*
 moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 carol::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 dave::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
@@ -11,10 +8,11 @@ moon::ipsec pool --leases 2> /dev/null
 moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
 dave::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/sql/ip-pool-db-restart/test.conf b/testing/tests/sql/ip-pool-db-restart/test.conf
index 450100f..ae4f834 100644
--- a/testing/tests/sql/ip-pool-db-restart/test.conf
+++ b/testing/tests/sql/ip-pool-db-restart/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="moon carol dave"
 # Guest instances on which databases are used
 #
 DBHOSTS="$IPSECHOSTS"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/sql/ip-pool-db/evaltest.dat b/testing/tests/sql/ip-pool-db/evaltest.dat
index cfa87ae..7996924 100644
--- a/testing/tests/sql/ip-pool-db/evaltest.dat
+++ b/testing/tests/sql/ip-pool-db/evaltest.dat
@@ -5,9 +5,8 @@ carol::cat /var/log/daemon.log::handling INTERNAL_IP4_NBNS attribute failed::YES
 carol::cat /var/log/daemon.log::handling APPLICATION_VERSION attribute failed::YES
 carol::ip addr list dev eth0::PH_IP_CAROL1::YES
 carol::ip route list table 220::10.1.0.0/16.*src PH_IP_CAROL1::YES
-carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
-carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.3.0.1] child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*lo [...]
 dave:: cat /var/log/daemon.log::installing new virtual IP PH_IP_DAVE1::YES
 dave:: cat /var/log/daemon.log::installing new virtual IP PH_IP_DAVE1::YES
 dave:: cat /var/log/daemon.log::installing DNS server PH_IP_WINNETOU::YES
@@ -16,21 +15,18 @@ dave:: cat /var/log/daemon.log::handling INTERNAL_IP4_NBNS attribute failed::YES
 dave:: cat /var/log/daemon.log::handling APPLICATION_VERSION attribute failed::YES
 dave:: ip addr list dev eth0::PH_IP_DAVE1::YES
 dave:: ip route list table 220::10.1.0.0/16.*src PH_IP_DAVE1::YES
-dave:: ipsec status 2> /dev/null::.*ESTABLISHED.*dave at strongswan.org.*moon.strongswan.org::YES
-dave:: ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
 dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.3.0.2] child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*loc [...]
 moon:: cat /var/log/daemon.log::peer requested virtual IP %any::YES
 moon:: cat /var/log/daemon.log::acquired new lease for address.*in pool.*bigpool::YES
 moon:: cat /var/log/daemon.log::assigning virtual IP::YES
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.3.0.1] child-sas.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts [...]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.3.0.2] child-sas.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts= [...]
 moon:: ipsec pool --status 2> /dev/null::dns servers: PH_IP_WINNETOU PH_IP_VENUS::YES
 moon:: ipsec pool --status 2> /dev/null::nbns servers: PH_IP_VENUS::YES
 moon:: ipsec pool --status 2> /dev/null::bigpool.*10.3.0.1.*10.3.0.6.*static.*2::YES
 moon:: ipsec pool --leases --filter pool=bigpool,addr=10.3.0.1,id=carol at strongswan.org 2> /dev/null::online::YES
 moon:: ipsec pool --leases --filter pool=bigpool,addr=10.3.0.2,id=dave at strongswan.org 2> /dev/null::online::YES
-moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*carol at strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*dave at strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw[{]1}.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]2}.*INSTALLED, TUNNEL::YES
 moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
 moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
 moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/sql/ip-pool-db/hosts/carol/etc/ipsec.d/data.sql b/testing/tests/sql/ip-pool-db/hosts/carol/etc/ipsec.d/data.sql
index 9ef560a..ab343f2 100644
--- a/testing/tests/sql/ip-pool-db/hosts/carol/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/ip-pool-db/hosts/carol/etc/ipsec.d/data.sql
@@ -117,7 +117,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/ip-pool-db/hosts/carol/etc/strongswan.conf b/testing/tests/sql/ip-pool-db/hosts/carol/etc/strongswan.conf
index 4346eca..310587e 100644
--- a/testing/tests/sql/ip-pool-db/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/sql/ip-pool-db/hosts/carol/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql resolve
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql resolve
 }
diff --git a/testing/tests/sql/ip-pool-db/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/sql/ip-pool-db/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/ip-pool-db/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/ip-pool-db/hosts/dave/etc/ipsec.d/data.sql b/testing/tests/sql/ip-pool-db/hosts/dave/etc/ipsec.d/data.sql
index 39f0549..ca6c5d9 100644
--- a/testing/tests/sql/ip-pool-db/hosts/dave/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/ip-pool-db/hosts/dave/etc/ipsec.d/data.sql
@@ -117,7 +117,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/ip-pool-db/hosts/dave/etc/strongswan.conf b/testing/tests/sql/ip-pool-db/hosts/dave/etc/strongswan.conf
index 4346eca..310587e 100644
--- a/testing/tests/sql/ip-pool-db/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/sql/ip-pool-db/hosts/dave/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql resolve
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql resolve
 }
diff --git a/testing/tests/sql/ip-pool-db/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/sql/ip-pool-db/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/ip-pool-db/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/ip-pool-db/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/ip-pool-db/hosts/moon/etc/ipsec.d/data.sql
index 8378364..e376536 100644
--- a/testing/tests/sql/ip-pool-db/hosts/moon/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/ip-pool-db/hosts/moon/etc/ipsec.d/data.sql
@@ -117,7 +117,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'rw', 'ipsec _updown iptables'
+  'rw', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/ip-pool-db/hosts/moon/etc/strongswan.conf b/testing/tests/sql/ip-pool-db/hosts/moon/etc/strongswan.conf
index 64e7cc7..2e9e646 100644
--- a/testing/tests/sql/ip-pool-db/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/sql/ip-pool-db/hosts/moon/etc/strongswan.conf
@@ -1,16 +1,12 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql attr-sql
+
   plugins {
     sql {
       database = sqlite:///etc/db.d/ipsec.db
     }
-  }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql attr-sql
-}
-
-libhydra {
-  plugins {
     attr-sql {
       database = sqlite:///etc/db.d/ipsec.db
     }
diff --git a/testing/tests/sql/ip-pool-db/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/sql/ip-pool-db/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/ip-pool-db/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/ip-pool-db/posttest.dat b/testing/tests/sql/ip-pool-db/posttest.dat
index 4706143..d7107cc 100644
--- a/testing/tests/sql/ip-pool-db/posttest.dat
+++ b/testing/tests/sql/ip-pool-db/posttest.dat
@@ -1,9 +1,8 @@
-carol::ipsec stop
-dave::ipsec stop
-moon::ipsec stop
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
-moon::dbdir-remove
-carol::dbdir-remove
-dave::dbdir-remove
diff --git a/testing/tests/sql/ip-pool-db/pretest.dat b/testing/tests/sql/ip-pool-db/pretest.dat
index 0cea9d8..4d89bed 100644
--- a/testing/tests/sql/ip-pool-db/pretest.dat
+++ b/testing/tests/sql/ip-pool-db/pretest.dat
@@ -1,6 +1,3 @@
-moon::rm /etc/ipsec.d/cacerts/*
-carol::rm /etc/ipsec.d/cacerts/*
-dave::rm /etc/ipsec.d/cacerts/*
 moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 carol::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 dave::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
@@ -10,10 +7,11 @@ dave::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
 dave::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/sql/ip-pool-db/test.conf b/testing/tests/sql/ip-pool-db/test.conf
index 450100f..ae4f834 100644
--- a/testing/tests/sql/ip-pool-db/test.conf
+++ b/testing/tests/sql/ip-pool-db/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="moon carol dave"
 # Guest instances on which databases are used
 #
 DBHOSTS="$IPSECHOSTS"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/sql/ip-split-pools-db-restart/evaltest.dat b/testing/tests/sql/ip-split-pools-db-restart/evaltest.dat
index 5f7f5ec..b777070 100644
--- a/testing/tests/sql/ip-split-pools-db-restart/evaltest.dat
+++ b/testing/tests/sql/ip-split-pools-db-restart/evaltest.dat
@@ -1,9 +1,7 @@
 dave::cat /var/log/daemon.log::installing new virtual IP 10.3.1.1::YES
-dave::ipsec status 2> /dev/null::home.*ESTABLISHED.*dave at strongswan.org.*moon.strongswan.org::YES
-dave::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.3.1.1] child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*loc [...]
 carol::cat /var/log/daemon.log::installing new virtual IP 10.3.0.1::YES
-carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
-carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.3.0.1] child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*lo [...]
 moon:: cat /var/log/daemon.log::acquired existing lease for address 10.3.1.1 in pool.*pool1::YES
 moon:: cat /var/log/daemon.log::assigning virtual IP 10.3.1.1 to peer::YES
 moon:: cat /var/log/daemon.log::acquired existing lease for address 10.3.0.1 in pool.*pool0::YES
@@ -12,7 +10,5 @@ moon:: ipsec pool --status 2> /dev/null::pool0.*10.3.0.1.*10.3.0.2.*static.*2 .*
 moon:: ipsec pool --status 2> /dev/null::pool1.*10.3.1.1.*10.3.1.2.*static.*2 .*1 .*1 ::YES
 moon:: ipsec pool --leases --filter pool=pool0,addr=10.3.0.1,id=carol at strongswan.org 2> /dev/null::online::YES
 moon:: ipsec pool --leases --filter pool=pool1,addr=10.3.1.1,id=dave at strongswan.org 2> /dev/null::online::YES
-moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*dave at strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*carol at strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw[{]1}.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]2}.*INSTALLED, TUNNEL::YES
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.3.0.1] child-sas.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts [...]
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.3.1.1] child-sas.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts= [...]
diff --git a/testing/tests/sql/ip-split-pools-db-restart/hosts/carol/etc/ipsec.d/data.sql b/testing/tests/sql/ip-split-pools-db-restart/hosts/carol/etc/ipsec.d/data.sql
index 4a5d349..d5c4452 100644
--- a/testing/tests/sql/ip-split-pools-db-restart/hosts/carol/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/ip-split-pools-db-restart/hosts/carol/etc/ipsec.d/data.sql
@@ -117,7 +117,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/ip-split-pools-db-restart/hosts/carol/etc/strongswan.conf b/testing/tests/sql/ip-split-pools-db-restart/hosts/carol/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/ip-split-pools-db-restart/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/sql/ip-split-pools-db-restart/hosts/carol/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/ip-split-pools-db-restart/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/sql/ip-split-pools-db-restart/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/ip-split-pools-db-restart/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/ip-split-pools-db-restart/hosts/dave/etc/ipsec.d/data.sql b/testing/tests/sql/ip-split-pools-db-restart/hosts/dave/etc/ipsec.d/data.sql
index 529574a..ddd5502 100644
--- a/testing/tests/sql/ip-split-pools-db-restart/hosts/dave/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/ip-split-pools-db-restart/hosts/dave/etc/ipsec.d/data.sql
@@ -116,7 +116,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/ip-split-pools-db-restart/hosts/dave/etc/strongswan.conf b/testing/tests/sql/ip-split-pools-db-restart/hosts/dave/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/ip-split-pools-db-restart/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/sql/ip-split-pools-db-restart/hosts/dave/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/ip-split-pools-db-restart/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/sql/ip-split-pools-db-restart/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/ip-split-pools-db-restart/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/ip-split-pools-db-restart/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/ip-split-pools-db-restart/hosts/moon/etc/ipsec.d/data.sql
index 31d9e1c..032b82b 100644
--- a/testing/tests/sql/ip-split-pools-db-restart/hosts/moon/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/ip-split-pools-db-restart/hosts/moon/etc/ipsec.d/data.sql
@@ -129,7 +129,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'rw', 'ipsec _updown iptables'
+  'rw', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/ip-split-pools-db-restart/hosts/moon/etc/strongswan.conf b/testing/tests/sql/ip-split-pools-db-restart/hosts/moon/etc/strongswan.conf
index 64e7cc7..2e9e646 100644
--- a/testing/tests/sql/ip-split-pools-db-restart/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/sql/ip-split-pools-db-restart/hosts/moon/etc/strongswan.conf
@@ -1,16 +1,12 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql attr-sql
+
   plugins {
     sql {
       database = sqlite:///etc/db.d/ipsec.db
     }
-  }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql attr-sql
-}
-
-libhydra {
-  plugins {
     attr-sql {
       database = sqlite:///etc/db.d/ipsec.db
     }
diff --git a/testing/tests/sql/ip-split-pools-db-restart/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/sql/ip-split-pools-db-restart/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/ip-split-pools-db-restart/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/ip-split-pools-db-restart/posttest.dat b/testing/tests/sql/ip-split-pools-db-restart/posttest.dat
index a851d09..b257564 100644
--- a/testing/tests/sql/ip-split-pools-db-restart/posttest.dat
+++ b/testing/tests/sql/ip-split-pools-db-restart/posttest.dat
@@ -1,3 +1,5 @@
-carol::ipsec stop
-dave::ipsec stop
-moon::ipsec stop
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
diff --git a/testing/tests/sql/ip-split-pools-db-restart/pretest.dat b/testing/tests/sql/ip-split-pools-db-restart/pretest.dat
index 706cb32..d0c7b9c 100644
--- a/testing/tests/sql/ip-split-pools-db-restart/pretest.dat
+++ b/testing/tests/sql/ip-split-pools-db-restart/pretest.dat
@@ -1,6 +1,3 @@
-moon::rm /etc/ipsec.d/cacerts/*
-carol::rm /etc/ipsec.d/cacerts/*
-dave::rm /etc/ipsec.d/cacerts/*
 moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 carol::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 dave::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
@@ -9,10 +6,11 @@ carol::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 dave::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 moon::ipsec pool --status 2> /dev/null
 moon::ipsec pool --leases 2> /dev/null
-moon::ipsec start
-dave::ipsec start
-carol::ipsec start
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/sql/ip-split-pools-db-restart/test.conf b/testing/tests/sql/ip-split-pools-db-restart/test.conf
index 450100f..ae4f834 100644
--- a/testing/tests/sql/ip-split-pools-db-restart/test.conf
+++ b/testing/tests/sql/ip-split-pools-db-restart/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="moon carol dave"
 # Guest instances on which databases are used
 #
 DBHOSTS="$IPSECHOSTS"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/sql/ip-split-pools-db/evaltest.dat b/testing/tests/sql/ip-split-pools-db/evaltest.dat
index f186d89..16ea228 100644
--- a/testing/tests/sql/ip-split-pools-db/evaltest.dat
+++ b/testing/tests/sql/ip-split-pools-db/evaltest.dat
@@ -1,9 +1,8 @@
 carol::cat /var/log/daemon.log::installing new virtual IP 10.3.0.1::YES
-carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
-carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.3.0.1] child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*lo [...]
 dave:: cat /var/log/daemon.log::installing new virtual IP 10.3.1.1::YES
-dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*dave at strongswan.org.*moon.strongswan.org::YES
-dave:: ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
+dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.3.1.1] child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*loc [...]
 moon:: cat /var/log/daemon.log::acquired new lease for address 10.3.0.1 in pool.*pool0::YES
 moon:: cat /var/log/daemon.log::assigning virtual IP 10.3.0.1 to peer::YES
 moon:: cat /var/log/daemon.log::no available address found in pool.*pool0::YES
@@ -13,5 +12,5 @@ moon:: ipsec pool --status 2> /dev/null::pool0.*10.3.0.1.*10.3.0.1.*static.*1 .*
 moon:: ipsec pool --status 2> /dev/null::pool1.*10.3.1.1.*10.3.1.1.*static.*1 .*1 .*1 ::YES
 moon:: ipsec pool --leases --filter pool=pool0,addr=10.3.0.1,id=carol at strongswan.org 2> /dev/null::online::YES
 moon:: ipsec pool --leases --filter pool=pool1,addr=10.3.1.1,id=dave at strongswan.org 2> /dev/null::online::YES
-moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*carol at strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*dave at strongswan.org::YES
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.3.0.1] child-sas.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts [...]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.3.1.1] child-sas.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts= [...]
diff --git a/testing/tests/sql/ip-split-pools-db/hosts/carol/etc/ipsec.d/data.sql b/testing/tests/sql/ip-split-pools-db/hosts/carol/etc/ipsec.d/data.sql
index 4a5d349..d5c4452 100644
--- a/testing/tests/sql/ip-split-pools-db/hosts/carol/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/ip-split-pools-db/hosts/carol/etc/ipsec.d/data.sql
@@ -117,7 +117,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/ip-split-pools-db/hosts/carol/etc/strongswan.conf b/testing/tests/sql/ip-split-pools-db/hosts/carol/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/ip-split-pools-db/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/sql/ip-split-pools-db/hosts/carol/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/ip-split-pools-db/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/sql/ip-split-pools-db/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/ip-split-pools-db/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/ip-split-pools-db/hosts/dave/etc/ipsec.d/data.sql b/testing/tests/sql/ip-split-pools-db/hosts/dave/etc/ipsec.d/data.sql
index a832d06..6f2d0fc 100644
--- a/testing/tests/sql/ip-split-pools-db/hosts/dave/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/ip-split-pools-db/hosts/dave/etc/ipsec.d/data.sql
@@ -117,7 +117,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/ip-split-pools-db/hosts/dave/etc/strongswan.conf b/testing/tests/sql/ip-split-pools-db/hosts/dave/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/ip-split-pools-db/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/sql/ip-split-pools-db/hosts/dave/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/ip-split-pools-db/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/sql/ip-split-pools-db/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/ip-split-pools-db/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/ip-split-pools-db/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/ip-split-pools-db/hosts/moon/etc/ipsec.d/data.sql
index 1861e5f..991bcba 100644
--- a/testing/tests/sql/ip-split-pools-db/hosts/moon/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/ip-split-pools-db/hosts/moon/etc/ipsec.d/data.sql
@@ -117,7 +117,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'rw', 'ipsec _updown iptables'
+  'rw', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/ip-split-pools-db/hosts/moon/etc/strongswan.conf b/testing/tests/sql/ip-split-pools-db/hosts/moon/etc/strongswan.conf
index 64e7cc7..2e9e646 100644
--- a/testing/tests/sql/ip-split-pools-db/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/sql/ip-split-pools-db/hosts/moon/etc/strongswan.conf
@@ -1,16 +1,12 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql attr-sql
+
   plugins {
     sql {
       database = sqlite:///etc/db.d/ipsec.db
     }
-  }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql attr-sql
-}
-
-libhydra {
-  plugins {
     attr-sql {
       database = sqlite:///etc/db.d/ipsec.db
     }
diff --git a/testing/tests/sql/ip-split-pools-db/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/sql/ip-split-pools-db/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/ip-split-pools-db/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/ip-split-pools-db/posttest.dat b/testing/tests/sql/ip-split-pools-db/posttest.dat
index a851d09..b257564 100644
--- a/testing/tests/sql/ip-split-pools-db/posttest.dat
+++ b/testing/tests/sql/ip-split-pools-db/posttest.dat
@@ -1,3 +1,5 @@
-carol::ipsec stop
-dave::ipsec stop
-moon::ipsec stop
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
diff --git a/testing/tests/sql/ip-split-pools-db/pretest.dat b/testing/tests/sql/ip-split-pools-db/pretest.dat
index e820c81..e1f0c22 100644
--- a/testing/tests/sql/ip-split-pools-db/pretest.dat
+++ b/testing/tests/sql/ip-split-pools-db/pretest.dat
@@ -1,6 +1,3 @@
-moon::rm /etc/ipsec.d/cacerts/*
-carol::rm /etc/ipsec.d/cacerts/*
-dave::rm /etc/ipsec.d/cacerts/*
 moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 carol::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 dave::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
@@ -8,10 +5,11 @@ moon::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 carol::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 dave::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 moon::ipsec pool --status 2> /dev/null
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/sql/ip-split-pools-db/test.conf b/testing/tests/sql/ip-split-pools-db/test.conf
index 450100f..5e41e93 100644
--- a/testing/tests/sql/ip-split-pools-db/test.conf
+++ b/testing/tests/sql/ip-split-pools-db/test.conf
@@ -23,3 +23,6 @@ IPSECHOSTS="moon carol dave"
 # Guest instances on which databases are used
 #
 DBHOSTS="$IPSECHOSTS"
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/sql/multi-level-ca/evaltest.dat b/testing/tests/sql/multi-level-ca/evaltest.dat
index 72a555d..a0eaae1 100644
--- a/testing/tests/sql/multi-level-ca/evaltest.dat
+++ b/testing/tests/sql/multi-level-ca/evaltest.dat
@@ -1,21 +1,17 @@
 carol::cat /var/log/daemon.log::sending issuer cert.*CN=Research CA::YES
+carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=[192.168.0.100/32 remote-t [...]
 dave:: cat /var/log/daemon.log::sending issuer cert.*CN=Sales CA::YES
+dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.200/3 [...]
 moon:: cat /var/log/daemon.log::fetching crl from.*http.*research.crl::YES
 moon:: cat /var/log/daemon.log::crl correctly signed by.*Research CA::YES
 moon:: cat /var/log/daemon.log::fetching crl from.*http.*sales.crl::YES
 moon:: cat /var/log/daemon.log::crl correctly signed by.*Sales CA::YES
 moon:: cat /var/log/daemon.log::fetching crl from.*http.*strongswan.crl::YES
 moon:: cat /var/log/daemon.log::crl correctly signed by.*strongSwan Root CA::YES
-carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
-dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*dave at strongswan.org.*moon.strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*carol at strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*dave at strongswan.org::YES
-carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-dave:: ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]1}.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]2}.*INSTALLED, TUNNEL::YES
-carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-t [...]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-ts [...]
 moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
 moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
 moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/sql/multi-level-ca/hosts/carol/etc/ipsec.d/data.sql b/testing/tests/sql/multi-level-ca/hosts/carol/etc/ipsec.d/data.sql
index bd2f3b8..b6e9c81 100644
--- a/testing/tests/sql/multi-level-ca/hosts/carol/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/multi-level-ca/hosts/carol/etc/ipsec.d/data.sql
@@ -156,7 +156,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/multi-level-ca/hosts/carol/etc/strongswan.conf b/testing/tests/sql/multi-level-ca/hosts/carol/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/multi-level-ca/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/sql/multi-level-ca/hosts/carol/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/multi-level-ca/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/sql/multi-level-ca/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/multi-level-ca/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/multi-level-ca/hosts/dave/etc/ipsec.d/data.sql b/testing/tests/sql/multi-level-ca/hosts/dave/etc/ipsec.d/data.sql
index eae9b59..ff60dd0 100644
--- a/testing/tests/sql/multi-level-ca/hosts/dave/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/multi-level-ca/hosts/dave/etc/ipsec.d/data.sql
@@ -159,7 +159,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/multi-level-ca/hosts/dave/etc/strongswan.conf b/testing/tests/sql/multi-level-ca/hosts/dave/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/multi-level-ca/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/sql/multi-level-ca/hosts/dave/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/multi-level-ca/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/sql/multi-level-ca/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/multi-level-ca/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/multi-level-ca/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/multi-level-ca/hosts/moon/etc/ipsec.d/data.sql
index 9d9564b..64c68e4 100644
--- a/testing/tests/sql/multi-level-ca/hosts/moon/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/multi-level-ca/hosts/moon/etc/ipsec.d/data.sql
@@ -129,7 +129,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'rw', 'ipsec _updown iptables'
+  'rw', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/multi-level-ca/hosts/moon/etc/strongswan.conf b/testing/tests/sql/multi-level-ca/hosts/moon/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/multi-level-ca/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/sql/multi-level-ca/hosts/moon/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/multi-level-ca/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/sql/multi-level-ca/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/multi-level-ca/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/multi-level-ca/posttest.dat b/testing/tests/sql/multi-level-ca/posttest.dat
index 1865a1c..d7107cc 100644
--- a/testing/tests/sql/multi-level-ca/posttest.dat
+++ b/testing/tests/sql/multi-level-ca/posttest.dat
@@ -1,6 +1,8 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/sql/multi-level-ca/pretest.dat b/testing/tests/sql/multi-level-ca/pretest.dat
index 0cea9d8..4d89bed 100644
--- a/testing/tests/sql/multi-level-ca/pretest.dat
+++ b/testing/tests/sql/multi-level-ca/pretest.dat
@@ -1,6 +1,3 @@
-moon::rm /etc/ipsec.d/cacerts/*
-carol::rm /etc/ipsec.d/cacerts/*
-dave::rm /etc/ipsec.d/cacerts/*
 moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 carol::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 dave::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
@@ -10,10 +7,11 @@ dave::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
 dave::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/sql/multi-level-ca/test.conf b/testing/tests/sql/multi-level-ca/test.conf
index f6fb44f..2b2019d 100644
--- a/testing/tests/sql/multi-level-ca/test.conf
+++ b/testing/tests/sql/multi-level-ca/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="moon carol dave"
 # Guest instances on which databases are used
 #
 DBHOSTS="$IPSECHOSTS"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/sql/net2net-cert/evaltest.dat b/testing/tests/sql/net2net-cert/evaltest.dat
index f003f82..5180ab3 100644
--- a/testing/tests/sql/net2net-cert/evaltest.dat
+++ b/testing/tests/sql/net2net-cert/evaltest.dat
@@ -1,7 +1,5 @@
-moon:: ipsec status 2> /dev/null::net-net.*ESTABLISHED.*moon.strongswan.org.*sun.strongswan.org::YES
-sun::  ipsec status 2> /dev/null::net-net.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES
-moon:: ipsec status 2> /dev/null::net-net.*INSTALLED, TUNNEL::YES
-sun::  ipsec status 2> /dev/null::net-net.*INSTALLED, TUNNEL::YES
+moon::swanctl --list-sas --raw 2> /dev/null::net-net.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-port=500 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_12.*local-ts=\[10.1.0.0/16] remote-ts=\ [...]
+sun:: swanctl --list-sas --raw 2> /dev/null::net-net.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=500 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-port=500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_12.*local-ts=\[10.2.0.0/16] remote-ts=\[10.1.0.0/16]::YES
 alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
 sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
 sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/sql/net2net-cert/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/net2net-cert/hosts/moon/etc/ipsec.d/data.sql
index d49fe49..3164151 100644
--- a/testing/tests/sql/net2net-cert/hosts/moon/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/net2net-cert/hosts/moon/etc/ipsec.d/data.sql
@@ -117,7 +117,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'net-net', 'ipsec _updown iptables'
+  'net-net', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/net2net-cert/hosts/moon/etc/strongswan.conf b/testing/tests/sql/net2net-cert/hosts/moon/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/net2net-cert/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/sql/net2net-cert/hosts/moon/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/net2net-cert/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/sql/net2net-cert/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/net2net-cert/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/net2net-cert/hosts/sun/etc/ipsec.d/data.sql b/testing/tests/sql/net2net-cert/hosts/sun/etc/ipsec.d/data.sql
index 938e507..47eabf2 100644
--- a/testing/tests/sql/net2net-cert/hosts/sun/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/net2net-cert/hosts/sun/etc/ipsec.d/data.sql
@@ -117,7 +117,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'net-net', 'ipsec _updown iptables'
+  'net-net', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/net2net-cert/hosts/sun/etc/strongswan.conf b/testing/tests/sql/net2net-cert/hosts/sun/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/net2net-cert/hosts/sun/etc/strongswan.conf
+++ b/testing/tests/sql/net2net-cert/hosts/sun/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/net2net-cert/hosts/sun/etc/swanctl/swanctl.conf b/testing/tests/sql/net2net-cert/hosts/sun/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/net2net-cert/hosts/sun/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/net2net-cert/posttest.dat b/testing/tests/sql/net2net-cert/posttest.dat
index 1f7aa73..59badb8 100644
--- a/testing/tests/sql/net2net-cert/posttest.dat
+++ b/testing/tests/sql/net2net-cert/posttest.dat
@@ -1,4 +1,4 @@
-moon::ipsec stop
-sun::ipsec stop
+moon::service charon stop 2> /dev/null
+sun::service charon stop 2> /dev/null
 moon::iptables-restore < /etc/iptables.flush
 sun::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/sql/net2net-cert/pretest.dat b/testing/tests/sql/net2net-cert/pretest.dat
index 05fe277..6580e76 100644
--- a/testing/tests/sql/net2net-cert/pretest.dat
+++ b/testing/tests/sql/net2net-cert/pretest.dat
@@ -1,12 +1,11 @@
-moon::rm /etc/ipsec.d/cacerts/*
-sun::rm /etc/ipsec.d/cacerts/*
 moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 sun::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 moon::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 sun::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 moon::iptables-restore < /etc/iptables.rules
 sun::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-sun::ipsec start
-moon::expect-connection net-net
-moon::ipsec up net-net
+moon::service charon start 2> /dev/null
+sun::service charon start 2> /dev/null
+moon::expect-connection net-net 
+sun::expect-connection net-net
+moon::swanctl --initiate --child net-net 2> /dev/null
diff --git a/testing/tests/sql/net2net-cert/test.conf b/testing/tests/sql/net2net-cert/test.conf
index 1b7e280..a553c6a 100644
--- a/testing/tests/sql/net2net-cert/test.conf
+++ b/testing/tests/sql/net2net-cert/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="moon sun"
 # Guest instances on which databases are used
 #
 DBHOSTS="$IPSECHOSTS"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/sql/net2net-psk/evaltest.dat b/testing/tests/sql/net2net-psk/evaltest.dat
index f003f82..5180ab3 100644
--- a/testing/tests/sql/net2net-psk/evaltest.dat
+++ b/testing/tests/sql/net2net-psk/evaltest.dat
@@ -1,7 +1,5 @@
-moon:: ipsec status 2> /dev/null::net-net.*ESTABLISHED.*moon.strongswan.org.*sun.strongswan.org::YES
-sun::  ipsec status 2> /dev/null::net-net.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES
-moon:: ipsec status 2> /dev/null::net-net.*INSTALLED, TUNNEL::YES
-sun::  ipsec status 2> /dev/null::net-net.*INSTALLED, TUNNEL::YES
+moon::swanctl --list-sas --raw 2> /dev/null::net-net.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-port=500 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_12.*local-ts=\[10.1.0.0/16] remote-ts=\ [...]
+sun:: swanctl --list-sas --raw 2> /dev/null::net-net.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=500 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-port=500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_12.*local-ts=\[10.2.0.0/16] remote-ts=\[10.1.0.0/16]::YES
 alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
 sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
 sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/sql/net2net-psk/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/net2net-psk/hosts/moon/etc/ipsec.d/data.sql
index aa6e84c..42116e2 100644
--- a/testing/tests/sql/net2net-psk/hosts/moon/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/net2net-psk/hosts/moon/etc/ipsec.d/data.sql
@@ -55,7 +55,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'net-net', 'ipsec _updown iptables'
+  'net-net', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/net2net-psk/hosts/moon/etc/strongswan.conf b/testing/tests/sql/net2net-psk/hosts/moon/etc/strongswan.conf
index e20fecc..6332df4 100644
--- a/testing/tests/sql/net2net-psk/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/sql/net2net-psk/hosts/moon/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/net2net-psk/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/sql/net2net-psk/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/net2net-psk/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/net2net-psk/hosts/sun/etc/ipsec.d/data.sql b/testing/tests/sql/net2net-psk/hosts/sun/etc/ipsec.d/data.sql
index 7c2865f..0942572 100644
--- a/testing/tests/sql/net2net-psk/hosts/sun/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/net2net-psk/hosts/sun/etc/ipsec.d/data.sql
@@ -49,7 +49,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'net-net', 'ipsec _updown iptables'
+  'net-net', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/net2net-psk/hosts/sun/etc/strongswan.conf b/testing/tests/sql/net2net-psk/hosts/sun/etc/strongswan.conf
index e20fecc..6332df4 100644
--- a/testing/tests/sql/net2net-psk/hosts/sun/etc/strongswan.conf
+++ b/testing/tests/sql/net2net-psk/hosts/sun/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/net2net-psk/hosts/sun/etc/swanctl/swanctl.conf b/testing/tests/sql/net2net-psk/hosts/sun/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/net2net-psk/hosts/sun/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/net2net-psk/posttest.dat b/testing/tests/sql/net2net-psk/posttest.dat
index 1f7aa73..59badb8 100644
--- a/testing/tests/sql/net2net-psk/posttest.dat
+++ b/testing/tests/sql/net2net-psk/posttest.dat
@@ -1,4 +1,4 @@
-moon::ipsec stop
-sun::ipsec stop
+moon::service charon stop 2> /dev/null
+sun::service charon stop 2> /dev/null
 moon::iptables-restore < /etc/iptables.flush
 sun::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/sql/net2net-psk/pretest.dat b/testing/tests/sql/net2net-psk/pretest.dat
index 05fe277..6580e76 100644
--- a/testing/tests/sql/net2net-psk/pretest.dat
+++ b/testing/tests/sql/net2net-psk/pretest.dat
@@ -1,12 +1,11 @@
-moon::rm /etc/ipsec.d/cacerts/*
-sun::rm /etc/ipsec.d/cacerts/*
 moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 sun::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 moon::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 sun::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 moon::iptables-restore < /etc/iptables.rules
 sun::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-sun::ipsec start
-moon::expect-connection net-net
-moon::ipsec up net-net
+moon::service charon start 2> /dev/null
+sun::service charon start 2> /dev/null
+moon::expect-connection net-net 
+sun::expect-connection net-net
+moon::swanctl --initiate --child net-net 2> /dev/null
diff --git a/testing/tests/sql/net2net-psk/test.conf b/testing/tests/sql/net2net-psk/test.conf
index 1b7e280..a553c6a 100644
--- a/testing/tests/sql/net2net-psk/test.conf
+++ b/testing/tests/sql/net2net-psk/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="moon sun"
 # Guest instances on which databases are used
 #
 DBHOSTS="$IPSECHOSTS"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/sql/net2net-route-pem/evaltest.dat b/testing/tests/sql/net2net-route-pem/evaltest.dat
index 2c85542..87af401 100644
--- a/testing/tests/sql/net2net-route-pem/evaltest.dat
+++ b/testing/tests/sql/net2net-route-pem/evaltest.dat
@@ -1,15 +1,7 @@
-moon:: ipsec status 2> /dev/null::net-1.*ROUTED, TUNNEL::YES
-sun::  ipsec status 2> /dev/null::net-1.*ROUTED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::net-2.*ROUTED, TUNNEL::YES
-sun::  ipsec status 2> /dev/null::net-2.*ROUTED, TUNNEL::YES
 moon:: cat /var/log/daemon.log::creating acquire job for policy 10.1.0.10/32\[icmp/8\] === 10.2.0.10/32\[icmp/8\] with reqid {1}::YES
-moon:: ipsec status 2> /dev/null::net-1.*INSTALLED, TUNNEL::YES
-sun::  ipsec status 2> /dev/null::net-1.*INSTALLED. TUNNEL::YES
 sun::  cat /var/log/daemon.log::creating acquire job for policy 10.2.0.10/32\[icmp/8\] === 10.1.0.20/32\[icmp/8\] with reqid {2}::YES
-moon:: ipsec status 2> /dev/null::net-net.*ESTABLISHED.*moon.strongswan.org.*sun.strongswan.org::YES
-sun::  ipsec status 2> /dev/null::net-net.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES
-moon:: ipsec status 2> /dev/null::net-2.*INSTALLED, TUNNEL::YES
-sun::  ipsec status 2> /dev/null::net-2.*INSTALLED, TUNNEL::YES
+moon::swanctl --list-sas --raw 2> /dev/null::net-net.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-port=500 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net-1.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/28] remo [...]
+sun:: swanctl --list-sas --raw 2> /dev/null::net-net.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=500 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-port=500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net-1.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.2.0.0/23] remote-ts=\[10.1.0 [...]
 alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
 bob::  ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
 sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
diff --git a/testing/tests/sql/net2net-route-pem/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/net2net-route-pem/hosts/moon/etc/ipsec.d/data.sql
index e161c6f..f0ae8c1 100644
--- a/testing/tests/sql/net2net-route-pem/hosts/moon/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/net2net-route-pem/hosts/moon/etc/ipsec.d/data.sql
@@ -131,19 +131,19 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown, start_action, dpd_action
 ) VALUES (
-  'net-1', 'ipsec _updown iptables', 1, 1
+  'net-1', '/usr/local/libexec/ipsec/_updown iptables', 1, 1
 );
 
 INSERT INTO child_configs (
   name, updown, start_action, dpd_action
 ) VALUES (
-  'net-2', 'ipsec _updown iptables', 1, 1
+  'net-2', '/usr/local/libexec/ipsec/_updown iptables', 1, 1
 );
 
 INSERT INTO child_configs (
   name, updown, start_action, dpd_action
 ) VALUES (
-  'net-3', 'ipsec _updown iptables', 0, 0
+  'net-3', '/usr/local/libexec/ipsec/_updown iptables', 0, 0
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/net2net-route-pem/hosts/moon/etc/strongswan.conf b/testing/tests/sql/net2net-route-pem/hosts/moon/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/net2net-route-pem/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/sql/net2net-route-pem/hosts/moon/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/net2net-route-pem/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/sql/net2net-route-pem/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/net2net-route-pem/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/net2net-route-pem/hosts/sun/etc/ipsec.d/data.sql b/testing/tests/sql/net2net-route-pem/hosts/sun/etc/ipsec.d/data.sql
index 27a40dd..4268f8e 100644
--- a/testing/tests/sql/net2net-route-pem/hosts/sun/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/net2net-route-pem/hosts/sun/etc/ipsec.d/data.sql
@@ -131,19 +131,19 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown, start_action, dpd_action
 ) VALUES (
-  'net-1', 'ipsec _updown iptables', 1, 1
+  'net-1', '/usr/local/libexec/ipsec/_updown iptables', 1, 1
 );
 
 INSERT INTO child_configs (
   name, updown, start_action, dpd_action
 ) VALUES (
-  'net-2', 'ipsec _updown iptables', 1, 1
+  'net-2', '/usr/local/libexec/ipsec/_updown iptables', 1, 1
 );
 
 INSERT INTO child_configs (
   name, updown, start_action, dpd_action
 ) VALUES (
-  'net-3', 'ipsec _updown iptables', 0, 0
+  'net-3', '/usr/local/libexec/ipsec/_updown iptables', 0, 0
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/net2net-route-pem/hosts/sun/etc/strongswan.conf b/testing/tests/sql/net2net-route-pem/hosts/sun/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/net2net-route-pem/hosts/sun/etc/strongswan.conf
+++ b/testing/tests/sql/net2net-route-pem/hosts/sun/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/net2net-route-pem/hosts/sun/etc/swanctl/swanctl.conf b/testing/tests/sql/net2net-route-pem/hosts/sun/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/net2net-route-pem/hosts/sun/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/net2net-route-pem/posttest.dat b/testing/tests/sql/net2net-route-pem/posttest.dat
index 1f7aa73..59badb8 100644
--- a/testing/tests/sql/net2net-route-pem/posttest.dat
+++ b/testing/tests/sql/net2net-route-pem/posttest.dat
@@ -1,4 +1,4 @@
-moon::ipsec stop
-sun::ipsec stop
+moon::service charon stop 2> /dev/null
+sun::service charon stop 2> /dev/null
 moon::iptables-restore < /etc/iptables.flush
 sun::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/sql/net2net-route-pem/pretest.dat b/testing/tests/sql/net2net-route-pem/pretest.dat
index cef74e4..576bd67 100644
--- a/testing/tests/sql/net2net-route-pem/pretest.dat
+++ b/testing/tests/sql/net2net-route-pem/pretest.dat
@@ -1,13 +1,11 @@
-moon::rm /etc/ipsec.d/cacerts/*
-sun::rm /etc/ipsec.d/cacerts/*
 moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 sun::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 moon::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 sun::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 moon::iptables-restore < /etc/iptables.rules
 sun::iptables-restore < /etc/iptables.rules
-sun::ipsec start
-moon::ipsec start
+moon::service charon start 2> /dev/null
+sun::service charon start 2> /dev/null
 moon::expect-connection net-net
-alice::ping -c 1 -W 1 PH_IP_BOB
-bob::ping -c 1 -W 1 PH_IP_VENUS
+alice::ping -c 1 -W 1 10.2.0.10
+bob::ping -c 1 -W 1 10.1.0.20
diff --git a/testing/tests/sql/net2net-route-pem/test.conf b/testing/tests/sql/net2net-route-pem/test.conf
index ee97968..1380836 100644
--- a/testing/tests/sql/net2net-route-pem/test.conf
+++ b/testing/tests/sql/net2net-route-pem/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="moon sun"
 # Guest instances on which databases are used
 #
 DBHOSTS="$IPSECHOSTS"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/sql/net2net-start-pem/evaltest.dat b/testing/tests/sql/net2net-start-pem/evaltest.dat
index 6534adc..630c17e 100644
--- a/testing/tests/sql/net2net-start-pem/evaltest.dat
+++ b/testing/tests/sql/net2net-start-pem/evaltest.dat
@@ -1,11 +1,5 @@
-moon:: ipsec status 2> /dev/null::net-net.*ESTABLISHED.*moon.strongswan.org.*sun.strongswan.org::YES
-sun::  ipsec status 2> /dev/null::net-net.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES
-moon:: ipsec status 2> /dev/null::net-1.*INSTALLED, TUNNEL::YES
-sun::  ipsec status 2> /dev/null::net-1.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::net-2.*INSTALLED, TUNNEL::YES
-sun::  ipsec status 2> /dev/null::net-2.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::net-3.*INSTALLED, TUNNEL::YES
-sun::  ipsec status 2> /dev/null::net-3.*INSTALLED, TUNNEL::YES
+moon:: swanctl --list-sas --raw 2> /dev/null::net-net.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-port=500 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net-1.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/28] remote-ts=\[10.2.0.0/23].*ne [...]
+sun::  swanctl --list-sas --raw 2> /dev/null::net-net.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=500 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-port=500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net-1.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.2.0.0/23] remote-ts=\[10.1.0.0/28].*net-2.*state=INS [...]
 alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
 bob::  ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
 sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
diff --git a/testing/tests/sql/net2net-start-pem/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/net2net-start-pem/hosts/moon/etc/ipsec.d/data.sql
index d178fe5..7db84f2 100644
--- a/testing/tests/sql/net2net-start-pem/hosts/moon/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/net2net-start-pem/hosts/moon/etc/ipsec.d/data.sql
@@ -105,25 +105,25 @@ INSERT INTO private_key_identity (
 INSERT INTO proposals (
   proposal
 ) VALUES (
-  'aes128-sha256-modp2048'
+  'aes128-sha256-modp3072'
 );
 
 INSERT INTO proposals (
   proposal
 ) VALUES (
-  'aes192-sha384-modp3072'
+  'aes192-sha384-modp8192'
 );
 
 INSERT INTO proposals (
   proposal
 ) VALUES (
-  'aes128gcm128'
+  'aes128gcm16-modp3072'
 );
 
 INSERT INTO proposals (
   proposal
 ) VALUES (
-  'aes192gcm128'
+  'aes192gcm16-modp8192'
 );
 
 /* Configurations */
@@ -155,19 +155,19 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown, start_action, dpd_action
 ) VALUES (
-  'net-1', 'ipsec _updown iptables', 2, 2
+  'net-1', '/usr/local/libexec/ipsec/_updown iptables', 2, 2
 );
 
 INSERT INTO child_configs (
   name, updown, start_action, dpd_action
 ) VALUES (
-  'net-2', 'ipsec _updown iptables', 2, 2
+  'net-2', '/usr/local/libexec/ipsec/_updown iptables', 2, 2
 );
 
 INSERT INTO child_configs (
   name, updown, start_action, dpd_action
 ) VALUES (
-  'net-3', 'ipsec _updown iptables', 2, 2
+  'net-3', '/usr/local/libexec/ipsec/_updown iptables', 2, 2
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/net2net-start-pem/hosts/moon/etc/strongswan.conf b/testing/tests/sql/net2net-start-pem/hosts/moon/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/net2net-start-pem/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/sql/net2net-start-pem/hosts/moon/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/net2net-start-pem/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/sql/net2net-start-pem/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/net2net-start-pem/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/net2net-start-pem/hosts/sun/etc/ipsec.d/data.sql b/testing/tests/sql/net2net-start-pem/hosts/sun/etc/ipsec.d/data.sql
index dd437b9..8d9d95d 100644
--- a/testing/tests/sql/net2net-start-pem/hosts/sun/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/net2net-start-pem/hosts/sun/etc/ipsec.d/data.sql
@@ -105,25 +105,25 @@ INSERT INTO private_key_identity (
 INSERT INTO proposals (
   proposal
 ) VALUES (
-  'aes128-sha256-modp2048'
+  'aes128-sha256-modp3072'
 );
 
 INSERT INTO proposals (
   proposal
 ) VALUES (
-  'aes192-sha384-modp3072'
+  'aes192-sha384-modp8192'
 );
 
 INSERT INTO proposals (
   proposal
 ) VALUES (
-  'aes128gcm128'
+  'aes128gcm16-modp3072'
 );
 
 INSERT INTO proposals (
   proposal
 ) VALUES (
-  'aes192gcm128'
+  'aes192gcm16-modp8192'
 );
 
 /* Configurations */
@@ -155,19 +155,19 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown, start_action, dpd_action
 ) VALUES (
-  'net-1', 'ipsec _updown iptables', 0, 0
+  'net-1', '/usr/local/libexec/ipsec/_updown iptables', 0, 0
 );
 
 INSERT INTO child_configs (
   name, updown, start_action, dpd_action
 ) VALUES (
-  'net-2', 'ipsec _updown iptables', 0, 0
+  'net-2', '/usr/local/libexec/ipsec/_updown iptables', 0, 0
 );
 
 INSERT INTO child_configs (
   name, updown, start_action, dpd_action
 ) VALUES (
-  'net-3', 'ipsec _updown iptables', 0, 0
+  'net-3', '/usr/local/libexec/ipsec/_updown iptables', 0, 0
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/net2net-start-pem/hosts/sun/etc/strongswan.conf b/testing/tests/sql/net2net-start-pem/hosts/sun/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/net2net-start-pem/hosts/sun/etc/strongswan.conf
+++ b/testing/tests/sql/net2net-start-pem/hosts/sun/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/net2net-start-pem/hosts/sun/etc/swanctl/swanctl.conf b/testing/tests/sql/net2net-start-pem/hosts/sun/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/net2net-start-pem/hosts/sun/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/net2net-start-pem/posttest.dat b/testing/tests/sql/net2net-start-pem/posttest.dat
index 1f7aa73..59badb8 100644
--- a/testing/tests/sql/net2net-start-pem/posttest.dat
+++ b/testing/tests/sql/net2net-start-pem/posttest.dat
@@ -1,4 +1,4 @@
-moon::ipsec stop
-sun::ipsec stop
+moon::service charon stop 2> /dev/null
+sun::service charon stop 2> /dev/null
 moon::iptables-restore < /etc/iptables.flush
 sun::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/sql/net2net-start-pem/pretest.dat b/testing/tests/sql/net2net-start-pem/pretest.dat
index f260b39..8fc6d1a 100644
--- a/testing/tests/sql/net2net-start-pem/pretest.dat
+++ b/testing/tests/sql/net2net-start-pem/pretest.dat
@@ -1,11 +1,11 @@
-moon::rm /etc/ipsec.d/cacerts/*
-sun::rm /etc/ipsec.d/cacerts/*
 moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 sun::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 moon::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 sun::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 moon::iptables-restore < /etc/iptables.rules
 sun::iptables-restore < /etc/iptables.rules
-sun::ipsec start
-moon::ipsec start
-moon::sleep 1
+sun::service charon start 2> /dev/null
+sun::expect-connection net-net
+moon::service charon start 2> /dev/null
+moon::sleep 4 
+
diff --git a/testing/tests/sql/net2net-start-pem/test.conf b/testing/tests/sql/net2net-start-pem/test.conf
index ee97968..1380836 100644
--- a/testing/tests/sql/net2net-start-pem/test.conf
+++ b/testing/tests/sql/net2net-start-pem/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="moon sun"
 # Guest instances on which databases are used
 #
 DBHOSTS="$IPSECHOSTS"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/sql/rw-cert/evaltest.dat b/testing/tests/sql/rw-cert/evaltest.dat
index 2342d02..bddf2fe 100644
--- a/testing/tests/sql/rw-cert/evaltest.dat
+++ b/testing/tests/sql/rw-cert/evaltest.dat
@@ -1,13 +1,9 @@
-carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
-dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*dave at strongswan.org.*moon.strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*carol at strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*dave at strongswan.org::YES
-carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-dave:: ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]1}.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]2}.*INSTALLED, TUNNEL::YES
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
 dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.100/ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.200/3 [...]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168. [...]
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168 [...]
 moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
 moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
 moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/sql/rw-cert/hosts/carol/etc/ipsec.d/data.sql b/testing/tests/sql/rw-cert/hosts/carol/etc/ipsec.d/data.sql
index 90c9a49..75c82fd 100644
--- a/testing/tests/sql/rw-cert/hosts/carol/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-cert/hosts/carol/etc/ipsec.d/data.sql
@@ -117,7 +117,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-cert/hosts/carol/etc/strongswan.conf b/testing/tests/sql/rw-cert/hosts/carol/etc/strongswan.conf
index 4946b15..22e6d14 100644
--- a/testing/tests/sql/rw-cert/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/sql/rw-cert/hosts/carol/etc/strongswan.conf
@@ -6,7 +6,7 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = test-vectors aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = test-vectors random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 
   integrity_test = yes
   crypto_test {
diff --git a/testing/tests/sql/rw-cert/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-cert/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-cert/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-cert/hosts/dave/etc/ipsec.d/data.sql b/testing/tests/sql/rw-cert/hosts/dave/etc/ipsec.d/data.sql
index 70afc34..88a3262 100644
--- a/testing/tests/sql/rw-cert/hosts/dave/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-cert/hosts/dave/etc/ipsec.d/data.sql
@@ -117,7 +117,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-cert/hosts/dave/etc/strongswan.conf b/testing/tests/sql/rw-cert/hosts/dave/etc/strongswan.conf
index 4946b15..22e6d14 100644
--- a/testing/tests/sql/rw-cert/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/sql/rw-cert/hosts/dave/etc/strongswan.conf
@@ -6,7 +6,7 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = test-vectors aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = test-vectors random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 
   integrity_test = yes
   crypto_test {
diff --git a/testing/tests/sql/rw-cert/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-cert/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-cert/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-cert/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/rw-cert/hosts/moon/etc/ipsec.d/data.sql
index 27e90de..9431647 100644
--- a/testing/tests/sql/rw-cert/hosts/moon/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-cert/hosts/moon/etc/ipsec.d/data.sql
@@ -117,7 +117,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'rw', 'ipsec _updown iptables'
+  'rw', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-cert/hosts/moon/etc/strongswan.conf b/testing/tests/sql/rw-cert/hosts/moon/etc/strongswan.conf
index 7fed45b..212dd3a 100644
--- a/testing/tests/sql/rw-cert/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/sql/rw-cert/hosts/moon/etc/strongswan.conf
@@ -6,7 +6,7 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = test-vectors aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = test-vectors random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 
   integrity_test = yes
 }
diff --git a/testing/tests/sql/rw-cert/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-cert/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-cert/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-cert/posttest.dat b/testing/tests/sql/rw-cert/posttest.dat
index 1865a1c..d7107cc 100644
--- a/testing/tests/sql/rw-cert/posttest.dat
+++ b/testing/tests/sql/rw-cert/posttest.dat
@@ -1,6 +1,8 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/sql/rw-cert/pretest.dat b/testing/tests/sql/rw-cert/pretest.dat
index 0cea9d8..4d89bed 100644
--- a/testing/tests/sql/rw-cert/pretest.dat
+++ b/testing/tests/sql/rw-cert/pretest.dat
@@ -1,6 +1,3 @@
-moon::rm /etc/ipsec.d/cacerts/*
-carol::rm /etc/ipsec.d/cacerts/*
-dave::rm /etc/ipsec.d/cacerts/*
 moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 carol::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 dave::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
@@ -10,10 +7,11 @@ dave::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
 dave::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/sql/rw-cert/test.conf b/testing/tests/sql/rw-cert/test.conf
index f6fb44f..2b2019d 100644
--- a/testing/tests/sql/rw-cert/test.conf
+++ b/testing/tests/sql/rw-cert/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="moon carol dave"
 # Guest instances on which databases are used
 #
 DBHOSTS="$IPSECHOSTS"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/sql/rw-eap-aka-rsa/evaltest.dat b/testing/tests/sql/rw-eap-aka-rsa/evaltest.dat
index 73173f0..4f3de0f 100644
--- a/testing/tests/sql/rw-eap-aka-rsa/evaltest.dat
+++ b/testing/tests/sql/rw-eap-aka-rsa/evaltest.dat
@@ -1,12 +1,8 @@
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA.* successful::YES
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
 moon:: cat /var/log/daemon.log::authentication of 'carol at strongswan.org' with EAP successful::YES
-carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw-eap-aka.*ESTABLISHED.*moon.strongswan.org.*carol at strongswan.org::YES
-carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw-eap-aka.*INSTALLED, TUNNEL::YES
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.100/ [...]
+moon:: swanctl --list-sas --raw 2> /dev/null::rw-eap-aka.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*rw-eap-aka.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-ts=\[19 [...]
 moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
 moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
-
-
diff --git a/testing/tests/sql/rw-eap-aka-rsa/hosts/carol/etc/ipsec.d/data.sql b/testing/tests/sql/rw-eap-aka-rsa/hosts/carol/etc/ipsec.d/data.sql
index 806a5b2..dfff084 100644
--- a/testing/tests/sql/rw-eap-aka-rsa/hosts/carol/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-eap-aka-rsa/hosts/carol/etc/ipsec.d/data.sql
@@ -93,7 +93,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-eap-aka-rsa/hosts/carol/etc/strongswan.conf b/testing/tests/sql/rw-eap-aka-rsa/hosts/carol/etc/strongswan.conf
index 2fba945..25a3b42 100644
--- a/testing/tests/sql/rw-eap-aka-rsa/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/sql/rw-eap-aka-rsa/hosts/carol/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 fips-prf pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql eap-aka eap-aka-3gpp2
+  load = random nonce aes sha1 sha2 fips-prf pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql eap-aka eap-aka-3gpp2
 }
diff --git a/testing/tests/sql/rw-eap-aka-rsa/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-eap-aka-rsa/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-eap-aka-rsa/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-eap-aka-rsa/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/rw-eap-aka-rsa/hosts/moon/etc/ipsec.d/data.sql
index 6b74f8b..02a9dfe 100644
--- a/testing/tests/sql/rw-eap-aka-rsa/hosts/moon/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-eap-aka-rsa/hosts/moon/etc/ipsec.d/data.sql
@@ -143,7 +143,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'rw-eap-aka', 'ipsec _updown iptables'
+  'rw-eap-aka', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-eap-aka-rsa/hosts/moon/etc/strongswan.conf b/testing/tests/sql/rw-eap-aka-rsa/hosts/moon/etc/strongswan.conf
index b06c611..34cc589 100644
--- a/testing/tests/sql/rw-eap-aka-rsa/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/sql/rw-eap-aka-rsa/hosts/moon/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 fips-prf pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default updown sqlite sql eap-aka eap-aka-3gpp2
+  load = random nonce aes sha1 sha2 fips-prf pem pkcs1 gmp x509 revocation hmac vici kernel-netlink socket-default updown sqlite sql eap-aka eap-aka-3gpp2
 }
diff --git a/testing/tests/sql/rw-eap-aka-rsa/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-eap-aka-rsa/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-eap-aka-rsa/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-eap-aka-rsa/posttest.dat b/testing/tests/sql/rw-eap-aka-rsa/posttest.dat
index 046d4cf..2fc2bbb 100644
--- a/testing/tests/sql/rw-eap-aka-rsa/posttest.dat
+++ b/testing/tests/sql/rw-eap-aka-rsa/posttest.dat
@@ -1,4 +1,5 @@
-moon::ipsec stop
-carol::ipsec stop
+carol::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/sql/rw-eap-aka-rsa/pretest.dat b/testing/tests/sql/rw-eap-aka-rsa/pretest.dat
index a6cbee7..d964629 100644
--- a/testing/tests/sql/rw-eap-aka-rsa/pretest.dat
+++ b/testing/tests/sql/rw-eap-aka-rsa/pretest.dat
@@ -1,12 +1,11 @@
-moon::rm /etc/ipsec.d/cacerts/*
-carol::rm /etc/ipsec.d/cacerts/*
 moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 carol::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 moon::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 carol::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-carol::ipsec start
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+moon::expect-connection rw-eap-aka
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/sql/rw-eap-aka-rsa/test.conf b/testing/tests/sql/rw-eap-aka-rsa/test.conf
index 81b1d3b..5bd7b14 100644
--- a/testing/tests/sql/rw-eap-aka-rsa/test.conf
+++ b/testing/tests/sql/rw-eap-aka-rsa/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="moon carol"
 # Guest instances on which databases are used
 #
 DBHOSTS="$IPSECHOSTS"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/sql/rw-psk-ipv4/evaltest.dat b/testing/tests/sql/rw-psk-ipv4/evaltest.dat
index eaf4739..80fd718 100644
--- a/testing/tests/sql/rw-psk-ipv4/evaltest.dat
+++ b/testing/tests/sql/rw-psk-ipv4/evaltest.dat
@@ -1,15 +1,10 @@
-carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*\[192.168.0.100].*\[192.168.0.1]::YES
-dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*\[192.168.0.200].*\[192.168.0.1]::YES
-moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*\[192.168.0.1].*\[192.168.0.100]::YES
-moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*\[192.168.0.1].*\[192.168.0.200]::YES
-carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-dave:: ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]1}.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]2}.*INSTALLED, TUNNEL::YES
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
 dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=192.168.0.100 remote-host=192.168.0.1 remote-port=4500 remote-id=192.168.0.1 initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.100/32] remote-ts=\ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=192.168.0.200 remote-host=192.168.0.1 remote-port=4500 remote-id=192.168.0.1 initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.200/32] remote-ts=\ [...]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=192.168.0.1 remote-host=192.168.0.200 remote-port=4500 remote-id=192.168.0.200.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]::YES
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=192.168.0.1 remote-host=192.168.0.100 remote-port=4500 remote-id=192.168.0.100.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]::YES
 moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
 moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
 moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
 moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES
-
diff --git a/testing/tests/sql/rw-psk-ipv4/hosts/carol/etc/ipsec.d/data.sql b/testing/tests/sql/rw-psk-ipv4/hosts/carol/etc/ipsec.d/data.sql
index a5ff52d..4b5b183 100644
--- a/testing/tests/sql/rw-psk-ipv4/hosts/carol/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-psk-ipv4/hosts/carol/etc/ipsec.d/data.sql
@@ -49,7 +49,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-psk-ipv4/hosts/carol/etc/strongswan.conf b/testing/tests/sql/rw-psk-ipv4/hosts/carol/etc/strongswan.conf
index e20fecc..6332df4 100644
--- a/testing/tests/sql/rw-psk-ipv4/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/sql/rw-psk-ipv4/hosts/carol/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/rw-psk-ipv4/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-psk-ipv4/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-psk-ipv4/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-psk-ipv4/hosts/dave/etc/ipsec.d/data.sql b/testing/tests/sql/rw-psk-ipv4/hosts/dave/etc/ipsec.d/data.sql
index ac39472..5aa53d6 100644
--- a/testing/tests/sql/rw-psk-ipv4/hosts/dave/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-psk-ipv4/hosts/dave/etc/ipsec.d/data.sql
@@ -49,7 +49,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-psk-ipv4/hosts/dave/etc/strongswan.conf b/testing/tests/sql/rw-psk-ipv4/hosts/dave/etc/strongswan.conf
index e20fecc..6332df4 100644
--- a/testing/tests/sql/rw-psk-ipv4/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/sql/rw-psk-ipv4/hosts/dave/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/rw-psk-ipv4/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-psk-ipv4/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-psk-ipv4/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-psk-ipv4/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/rw-psk-ipv4/hosts/moon/etc/ipsec.d/data.sql
index 231b84c..3d2f5d8 100644
--- a/testing/tests/sql/rw-psk-ipv4/hosts/moon/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-psk-ipv4/hosts/moon/etc/ipsec.d/data.sql
@@ -79,7 +79,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'rw', 'ipsec _updown iptables'
+  'rw', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-psk-ipv4/hosts/moon/etc/strongswan.conf b/testing/tests/sql/rw-psk-ipv4/hosts/moon/etc/strongswan.conf
index e20fecc..6332df4 100644
--- a/testing/tests/sql/rw-psk-ipv4/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/sql/rw-psk-ipv4/hosts/moon/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/rw-psk-ipv4/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-psk-ipv4/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-psk-ipv4/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-psk-ipv4/posttest.dat b/testing/tests/sql/rw-psk-ipv4/posttest.dat
index 1865a1c..d7107cc 100644
--- a/testing/tests/sql/rw-psk-ipv4/posttest.dat
+++ b/testing/tests/sql/rw-psk-ipv4/posttest.dat
@@ -1,6 +1,8 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/sql/rw-psk-ipv4/pretest.dat b/testing/tests/sql/rw-psk-ipv4/pretest.dat
index 0cea9d8..4d89bed 100644
--- a/testing/tests/sql/rw-psk-ipv4/pretest.dat
+++ b/testing/tests/sql/rw-psk-ipv4/pretest.dat
@@ -1,6 +1,3 @@
-moon::rm /etc/ipsec.d/cacerts/*
-carol::rm /etc/ipsec.d/cacerts/*
-dave::rm /etc/ipsec.d/cacerts/*
 moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 carol::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 dave::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
@@ -10,10 +7,11 @@ dave::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
 dave::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/sql/rw-psk-ipv4/test.conf b/testing/tests/sql/rw-psk-ipv4/test.conf
index f6fb44f..2b2019d 100644
--- a/testing/tests/sql/rw-psk-ipv4/test.conf
+++ b/testing/tests/sql/rw-psk-ipv4/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="moon carol dave"
 # Guest instances on which databases are used
 #
 DBHOSTS="$IPSECHOSTS"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/sql/rw-psk-ipv6/evaltest.dat b/testing/tests/sql/rw-psk-ipv6/evaltest.dat
index 344dfa8..63c8b64 100644
--- a/testing/tests/sql/rw-psk-ipv6/evaltest.dat
+++ b/testing/tests/sql/rw-psk-ipv6/evaltest.dat
@@ -1,15 +1,10 @@
-carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*\[fec0.*10].*\[fec0.*1]::YES
-dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*\[fec0.*20].*\[fec0.*1]::YES
-moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*\[fec0.*1].*\[fec0.*10]::YES
-moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*\[fec0.*1].*\[fec0.*20]::YES
-carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-dave:: ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]1}.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]2}.*INSTALLED, TUNNEL::YES
 carol::ping6 -c 1 ip6-alice.strongswan.org::64 bytes from ip6-alice.strongswan.org: icmp_seq=1::YES
 dave:: ping6 -c 1 ip6-alice.strongswan.org::64 bytes from ip6-alice.strongswan.org: icmp_seq=1::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=fec0:\:10 local-port=4500 local-id=fec0:\:10 remote-host=fec0:\:1 remote-port=4500 remote-id=fec0:\:1 initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[fec0:\:10/128] remote-ts=\[fec1:\:/16]::YES
+dave::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=fec0:\:20 local-port=4500 local-id=fec0:\:20 remote-host=fec0:\:1 remote-port=4500 remote-id=fec0:\:1 initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[fec0:\:20/128] remote-ts=\[fec1:\:/16]::YES
+moon::swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=fec0:\:1 local-port=4500 local-id=fec0:\:1 remote-host=fec0:\:10 remote-port=4500 remote-id=fec0:\:10.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[fec1:\:/16] remote-ts=\[fec0:\:10/128]::YES
+moon::swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=fec0:\:1 local-port=4500 local-id=fec0:\:1 remote-host=fec0:\:20 remote-port=4500 remote-id=fec0:\:20.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[fec1:\:/16] remote-ts=\[fec0:\:20/128]::YES
 moon::tcpdump::IP6 ip6-carol.strongswan.org > ip6-moon.strongswan.org: ESP::YES
 moon::tcpdump::IP6 ip6-moon.strongswan.org > ip6-carol.strongswan.org: ESP::YES
 moon::tcpdump::IP6 ip6-dave.strongswan.org > ip6-moon.strongswan.org: ESP::YES
 moon::tcpdump::IP6 ip6-moon.strongswan.org > ip6-dave.strongswan.org: ESP::YES
-
diff --git a/testing/tests/sql/rw-psk-ipv6/hosts/carol/etc/ipsec.d/data.sql b/testing/tests/sql/rw-psk-ipv6/hosts/carol/etc/ipsec.d/data.sql
index 8cbb82d..031303d 100644
--- a/testing/tests/sql/rw-psk-ipv6/hosts/carol/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-psk-ipv6/hosts/carol/etc/ipsec.d/data.sql
@@ -49,7 +49,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-psk-ipv6/hosts/carol/etc/strongswan.conf b/testing/tests/sql/rw-psk-ipv6/hosts/carol/etc/strongswan.conf
index e20fecc..6332df4 100644
--- a/testing/tests/sql/rw-psk-ipv6/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/sql/rw-psk-ipv6/hosts/carol/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/rw-psk-ipv6/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-psk-ipv6/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-psk-ipv6/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-psk-ipv6/hosts/dave/etc/ipsec.d/data.sql b/testing/tests/sql/rw-psk-ipv6/hosts/dave/etc/ipsec.d/data.sql
index 87055a2..fd91771 100644
--- a/testing/tests/sql/rw-psk-ipv6/hosts/dave/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-psk-ipv6/hosts/dave/etc/ipsec.d/data.sql
@@ -49,7 +49,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-psk-ipv6/hosts/dave/etc/strongswan.conf b/testing/tests/sql/rw-psk-ipv6/hosts/dave/etc/strongswan.conf
index e20fecc..6332df4 100644
--- a/testing/tests/sql/rw-psk-ipv6/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/sql/rw-psk-ipv6/hosts/dave/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/rw-psk-ipv6/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-psk-ipv6/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-psk-ipv6/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-psk-ipv6/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/rw-psk-ipv6/hosts/moon/etc/ipsec.d/data.sql
index 2479bea..0d94f34 100644
--- a/testing/tests/sql/rw-psk-ipv6/hosts/moon/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-psk-ipv6/hosts/moon/etc/ipsec.d/data.sql
@@ -79,7 +79,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'rw', 'ipsec _updown iptables'
+  'rw', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-psk-ipv6/hosts/moon/etc/strongswan.conf b/testing/tests/sql/rw-psk-ipv6/hosts/moon/etc/strongswan.conf
index e20fecc..6332df4 100644
--- a/testing/tests/sql/rw-psk-ipv6/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/sql/rw-psk-ipv6/hosts/moon/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/rw-psk-ipv6/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-psk-ipv6/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-psk-ipv6/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-psk-ipv6/posttest.dat b/testing/tests/sql/rw-psk-ipv6/posttest.dat
index 4e59395..3f82576 100644
--- a/testing/tests/sql/rw-psk-ipv6/posttest.dat
+++ b/testing/tests/sql/rw-psk-ipv6/posttest.dat
@@ -1,6 +1,8 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/sql/rw-psk-ipv6/pretest.dat b/testing/tests/sql/rw-psk-ipv6/pretest.dat
index 8946896..60a1055 100644
--- a/testing/tests/sql/rw-psk-ipv6/pretest.dat
+++ b/testing/tests/sql/rw-psk-ipv6/pretest.dat
@@ -1,6 +1,3 @@
-moon::rm /etc/ipsec.d/cacerts/*
-carol::rm /etc/ipsec.d/cacerts/*
-dave::rm /etc/ipsec.d/cacerts/*
 moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 carol::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 dave::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
@@ -16,10 +13,11 @@ dave::ip6tables-restore < /etc/ip6tables.rules
 alice::"ip route add fec0:\:/16 via fec1:\:1"
 carol::"ip route add fec1:\:/16 via fec0:\:1"
 dave::"ip route add fec1:\:/16 via fec0:\:1"
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/sql/rw-psk-ipv6/test.conf b/testing/tests/sql/rw-psk-ipv6/test.conf
index 024105e..2b2019d 100644
--- a/testing/tests/sql/rw-psk-ipv6/test.conf
+++ b/testing/tests/sql/rw-psk-ipv6/test.conf
@@ -9,7 +9,7 @@ VIRTHOSTS="alice moon carol winnetou dave"
 
 # Corresponding block diagram
 #
-DIAGRAM="a-m-c-w-d-ip6.png"
+DIAGRAM="a-m-c-w-d.png"
 
 # Guest instances on which tcpdump is to be started
 #
@@ -23,3 +23,7 @@ IPSECHOSTS="moon carol dave"
 # Guest instances on which databases are used
 #
 DBHOSTS="$IPSECHOSTS"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/sql/rw-psk-rsa-split/evaltest.dat b/testing/tests/sql/rw-psk-rsa-split/evaltest.dat
index 1206ea4..d3ddd8c 100644
--- a/testing/tests/sql/rw-psk-rsa-split/evaltest.dat
+++ b/testing/tests/sql/rw-psk-rsa-split/evaltest.dat
@@ -1,16 +1,12 @@
 moon:: cat /var/log/daemon.log::authentication of 'carol at strongswan.org' with pre-shared key successful::YES
 moon:: cat /var/log/daemon.log::authentication of 'dave at strongswan.org' with pre-shared key successful::YES
 moon:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' (myself) with RSA.* successful::YES
-carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
-dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*dave at strongswan.org.*moon.strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*carol at strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*dave at strongswan.org::YES
-carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-dave:: ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]1}.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]2}.*INSTALLED, TUNNEL::YES
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
 dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.100/ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.200/3 [...]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168. [...]
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168 [...]
 moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
 moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
 moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/sql/rw-psk-rsa-split/hosts/carol/etc/ipsec.d/data.sql b/testing/tests/sql/rw-psk-rsa-split/hosts/carol/etc/ipsec.d/data.sql
index c6c08a0..37e8b09 100644
--- a/testing/tests/sql/rw-psk-rsa-split/hosts/carol/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-psk-rsa-split/hosts/carol/etc/ipsec.d/data.sql
@@ -93,7 +93,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-psk-rsa-split/hosts/carol/etc/strongswan.conf b/testing/tests/sql/rw-psk-rsa-split/hosts/carol/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/rw-psk-rsa-split/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/sql/rw-psk-rsa-split/hosts/carol/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/rw-psk-rsa-split/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-psk-rsa-split/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-psk-rsa-split/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-psk-rsa-split/hosts/dave/etc/ipsec.d/data.sql b/testing/tests/sql/rw-psk-rsa-split/hosts/dave/etc/ipsec.d/data.sql
index 3620f20..724ace3 100644
--- a/testing/tests/sql/rw-psk-rsa-split/hosts/dave/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-psk-rsa-split/hosts/dave/etc/ipsec.d/data.sql
@@ -94,7 +94,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-psk-rsa-split/hosts/dave/etc/strongswan.conf b/testing/tests/sql/rw-psk-rsa-split/hosts/dave/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/rw-psk-rsa-split/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/sql/rw-psk-rsa-split/hosts/dave/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/rw-psk-rsa-split/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-psk-rsa-split/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-psk-rsa-split/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-psk-rsa-split/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/rw-psk-rsa-split/hosts/moon/etc/ipsec.d/data.sql
index a3d480f..d1349f9 100644
--- a/testing/tests/sql/rw-psk-rsa-split/hosts/moon/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-psk-rsa-split/hosts/moon/etc/ipsec.d/data.sql
@@ -168,7 +168,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'rw', 'ipsec _updown iptables'
+  'rw', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-psk-rsa-split/hosts/moon/etc/strongswan.conf b/testing/tests/sql/rw-psk-rsa-split/hosts/moon/etc/strongswan.conf
index 8b25be7..f5b531d 100644
--- a/testing/tests/sql/rw-psk-rsa-split/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/sql/rw-psk-rsa-split/hosts/moon/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/rw-psk-rsa-split/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-psk-rsa-split/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-psk-rsa-split/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-psk-rsa-split/posttest.dat b/testing/tests/sql/rw-psk-rsa-split/posttest.dat
index 1865a1c..d7107cc 100644
--- a/testing/tests/sql/rw-psk-rsa-split/posttest.dat
+++ b/testing/tests/sql/rw-psk-rsa-split/posttest.dat
@@ -1,6 +1,8 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/sql/rw-psk-rsa-split/pretest.dat b/testing/tests/sql/rw-psk-rsa-split/pretest.dat
index 0cea9d8..4d89bed 100644
--- a/testing/tests/sql/rw-psk-rsa-split/pretest.dat
+++ b/testing/tests/sql/rw-psk-rsa-split/pretest.dat
@@ -1,6 +1,3 @@
-moon::rm /etc/ipsec.d/cacerts/*
-carol::rm /etc/ipsec.d/cacerts/*
-dave::rm /etc/ipsec.d/cacerts/*
 moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 carol::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 dave::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
@@ -10,10 +7,11 @@ dave::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
 dave::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/sql/rw-psk-rsa-split/test.conf b/testing/tests/sql/rw-psk-rsa-split/test.conf
index f6fb44f..2b2019d 100644
--- a/testing/tests/sql/rw-psk-rsa-split/test.conf
+++ b/testing/tests/sql/rw-psk-rsa-split/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="moon carol dave"
 # Guest instances on which databases are used
 #
 DBHOSTS="$IPSECHOSTS"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/sql/rw-rsa-keyid/evaltest.dat b/testing/tests/sql/rw-rsa-keyid/evaltest.dat
index 4f5cd72..8d6c64a 100644
--- a/testing/tests/sql/rw-rsa-keyid/evaltest.dat
+++ b/testing/tests/sql/rw-rsa-keyid/evaltest.dat
@@ -1,13 +1,9 @@
-carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*1f:a1:.*:6e:7c.*6a:9c:.*:29:2e::YES
-dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*ee:7f:.*:8e:0e.*6a:9c:.*:29:2e::YES
-moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*6a:9c:.*:29:2e.*1f:a1:.*:6e:7c::YES
-moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*6a:9c:.*:29:2e.*ee:7f:.*:8e:0e::YES
-carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-dave:: ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]1}.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]2}.*INSTALLED, TUNNEL::YES
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
 dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=1f:a1:.*:6e:7c remote-host=192.168.0.1 remote-port=4500 remote-id=6a:9c:.*:29:2e initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.100/32] remote- [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=ee:7f:.*:8e:0e remote-host=192.168.0.1 remote-port=4500 remote-id=6a:9c:.*:29:2e initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.200/32] remote- [...]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=6a:9c:.*:29:2e remote-host=192.168.0.200 remote-port=4500 remote-id=ee:7f:.*:8e:0e.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]::YES
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=6a:9c:.*:29:2e remote-host=192.168.0.100 remote-port=4500 remote-id=1f:a1:.*:6e:7c.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]::YES
 moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
 moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
 moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/sql/rw-rsa-keyid/hosts/carol/etc/ipsec.d/data.sql b/testing/tests/sql/rw-rsa-keyid/hosts/carol/etc/ipsec.d/data.sql
index 4f181b9..ebec5c1 100644
--- a/testing/tests/sql/rw-rsa-keyid/hosts/carol/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-rsa-keyid/hosts/carol/etc/ipsec.d/data.sql
@@ -99,7 +99,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-rsa-keyid/hosts/carol/etc/strongswan.conf b/testing/tests/sql/rw-rsa-keyid/hosts/carol/etc/strongswan.conf
index 75a2b06..43ece90 100644
--- a/testing/tests/sql/rw-rsa-keyid/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/sql/rw-rsa-keyid/hosts/carol/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 pubkey gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 pubkey gmp hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/rw-rsa-keyid/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-rsa-keyid/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-rsa-keyid/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-rsa-keyid/hosts/dave/etc/ipsec.d/data.sql b/testing/tests/sql/rw-rsa-keyid/hosts/dave/etc/ipsec.d/data.sql
index 9a36c2c..961dd65 100644
--- a/testing/tests/sql/rw-rsa-keyid/hosts/dave/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-rsa-keyid/hosts/dave/etc/ipsec.d/data.sql
@@ -99,7 +99,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-rsa-keyid/hosts/dave/etc/strongswan.conf b/testing/tests/sql/rw-rsa-keyid/hosts/dave/etc/strongswan.conf
index 75a2b06..43ece90 100644
--- a/testing/tests/sql/rw-rsa-keyid/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/sql/rw-rsa-keyid/hosts/dave/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 pubkey gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 pubkey gmp hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/rw-rsa-keyid/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-rsa-keyid/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-rsa-keyid/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-rsa-keyid/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/rw-rsa-keyid/hosts/moon/etc/ipsec.d/data.sql
index 9718a75..dee634c 100644
--- a/testing/tests/sql/rw-rsa-keyid/hosts/moon/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-rsa-keyid/hosts/moon/etc/ipsec.d/data.sql
@@ -135,7 +135,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'rw', 'ipsec _updown iptables'
+  'rw', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-rsa-keyid/hosts/moon/etc/strongswan.conf b/testing/tests/sql/rw-rsa-keyid/hosts/moon/etc/strongswan.conf
index 75a2b06..43ece90 100644
--- a/testing/tests/sql/rw-rsa-keyid/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/sql/rw-rsa-keyid/hosts/moon/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 pubkey gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 pubkey gmp hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/rw-rsa-keyid/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-rsa-keyid/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-rsa-keyid/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-rsa-keyid/posttest.dat b/testing/tests/sql/rw-rsa-keyid/posttest.dat
index 1865a1c..d7107cc 100644
--- a/testing/tests/sql/rw-rsa-keyid/posttest.dat
+++ b/testing/tests/sql/rw-rsa-keyid/posttest.dat
@@ -1,6 +1,8 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/sql/rw-rsa-keyid/pretest.dat b/testing/tests/sql/rw-rsa-keyid/pretest.dat
index 0cea9d8..4d89bed 100644
--- a/testing/tests/sql/rw-rsa-keyid/pretest.dat
+++ b/testing/tests/sql/rw-rsa-keyid/pretest.dat
@@ -1,6 +1,3 @@
-moon::rm /etc/ipsec.d/cacerts/*
-carol::rm /etc/ipsec.d/cacerts/*
-dave::rm /etc/ipsec.d/cacerts/*
 moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 carol::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 dave::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
@@ -10,10 +7,11 @@ dave::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
 dave::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/sql/rw-rsa-keyid/test.conf b/testing/tests/sql/rw-rsa-keyid/test.conf
index f6fb44f..2b2019d 100644
--- a/testing/tests/sql/rw-rsa-keyid/test.conf
+++ b/testing/tests/sql/rw-rsa-keyid/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="moon carol dave"
 # Guest instances on which databases are used
 #
 DBHOSTS="$IPSECHOSTS"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/sql/rw-rsa/evaltest.dat b/testing/tests/sql/rw-rsa/evaltest.dat
index ba66197..b28e4c4 100644
--- a/testing/tests/sql/rw-rsa/evaltest.dat
+++ b/testing/tests/sql/rw-rsa/evaltest.dat
@@ -1,13 +1,9 @@
-carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*moon.strongswan.org::YES
-dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*dave at strongswan.org.*moon.strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*carol at strongswan.org::YES
-moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*dave at strongswan.org::YES
-carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-dave:: ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]1}.*INSTALLED, TUNNEL::YES
-moon:: ipsec status 2> /dev/null::rw[{]2}.*INSTALLED, TUNNEL::YES
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
 dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.100/ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.200/3 [...]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168. [...]
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168 [...]
 moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
 moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
 moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/sql/rw-rsa/hosts/carol/etc/ipsec.d/data.sql b/testing/tests/sql/rw-rsa/hosts/carol/etc/ipsec.d/data.sql
index 8219bdf..987e4ad 100644
--- a/testing/tests/sql/rw-rsa/hosts/carol/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-rsa/hosts/carol/etc/ipsec.d/data.sql
@@ -99,7 +99,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-rsa/hosts/carol/etc/strongswan.conf b/testing/tests/sql/rw-rsa/hosts/carol/etc/strongswan.conf
index 75a2b06..43ece90 100644
--- a/testing/tests/sql/rw-rsa/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/sql/rw-rsa/hosts/carol/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 pubkey gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 pubkey gmp hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/rw-rsa/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-rsa/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-rsa/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-rsa/hosts/dave/etc/ipsec.d/data.sql b/testing/tests/sql/rw-rsa/hosts/dave/etc/ipsec.d/data.sql
index 7c9cd9f..fda055a 100644
--- a/testing/tests/sql/rw-rsa/hosts/dave/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-rsa/hosts/dave/etc/ipsec.d/data.sql
@@ -98,7 +98,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'home', 'ipsec _updown iptables'
+  'home', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-rsa/hosts/dave/etc/strongswan.conf b/testing/tests/sql/rw-rsa/hosts/dave/etc/strongswan.conf
index 75a2b06..43ece90 100644
--- a/testing/tests/sql/rw-rsa/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/sql/rw-rsa/hosts/dave/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 pubkey gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 pubkey gmp hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/rw-rsa/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-rsa/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-rsa/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-rsa/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/rw-rsa/hosts/moon/etc/ipsec.d/data.sql
index 8a4eb2d..bc18a87 100644
--- a/testing/tests/sql/rw-rsa/hosts/moon/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/rw-rsa/hosts/moon/etc/ipsec.d/data.sql
@@ -135,7 +135,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'rw', 'ipsec _updown iptables'
+  'rw', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/rw-rsa/hosts/moon/etc/strongswan.conf b/testing/tests/sql/rw-rsa/hosts/moon/etc/strongswan.conf
index 75a2b06..43ece90 100644
--- a/testing/tests/sql/rw-rsa/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/sql/rw-rsa/hosts/moon/etc/strongswan.conf
@@ -6,5 +6,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 pubkey gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 pubkey gmp hmac vici kernel-netlink socket-default updown sqlite sql
 }
diff --git a/testing/tests/sql/rw-rsa/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/sql/rw-rsa/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/rw-rsa/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/rw-rsa/posttest.dat b/testing/tests/sql/rw-rsa/posttest.dat
index 1865a1c..d7107cc 100644
--- a/testing/tests/sql/rw-rsa/posttest.dat
+++ b/testing/tests/sql/rw-rsa/posttest.dat
@@ -1,6 +1,8 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/sql/rw-rsa/pretest.dat b/testing/tests/sql/rw-rsa/pretest.dat
index 0cea9d8..4d89bed 100644
--- a/testing/tests/sql/rw-rsa/pretest.dat
+++ b/testing/tests/sql/rw-rsa/pretest.dat
@@ -1,6 +1,3 @@
-moon::rm /etc/ipsec.d/cacerts/*
-carol::rm /etc/ipsec.d/cacerts/*
-dave::rm /etc/ipsec.d/cacerts/*
 moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 carol::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 dave::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
@@ -10,10 +7,11 @@ dave::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
 dave::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/sql/rw-rsa/test.conf b/testing/tests/sql/rw-rsa/test.conf
index f6fb44f..2b2019d 100644
--- a/testing/tests/sql/rw-rsa/test.conf
+++ b/testing/tests/sql/rw-rsa/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="moon carol dave"
 # Guest instances on which databases are used
 #
 DBHOSTS="$IPSECHOSTS"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/sql/shunt-policies-nat-rw/evaltest.dat b/testing/tests/sql/shunt-policies-nat-rw/evaltest.dat
index 4d36673..8b11737 100644
--- a/testing/tests/sql/shunt-policies-nat-rw/evaltest.dat
+++ b/testing/tests/sql/shunt-policies-nat-rw/evaltest.dat
@@ -1,12 +1,15 @@
-alice::ipsec status 2> /dev/null::local-net.*PASS::YES
-venus::ipsec status 2> /dev/null::local-net.*PASS::YES
-alice::ipsec status 2> /dev/null::nat-t.*ESTABLISHED.*alice at strongswan.org.*sun.strongswan.org::YES
-venus::ipsec status 2> /dev/null::nat-t.*ESTABLISHED.*venus.strongswan.org.*sun.strongswan.org::YES
 alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
 alice::ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
 venus::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
 venus::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+alice::swanctl --list-pols --raw 2> /dev/null::local-net.*mode=PASS local-ts=\[10.1.0.0/16] remote-ts=\[10.1.0.0/16]::YES
+venus::swanctl --list-pols --raw 2> /dev/null::local-net.*mode=PASS local-ts=\[10.1.0.0/16] remote-ts=\[10.1.0.0/16]::YES
+alice::swanctl --list-sas --raw 2> /dev/null::nat-t.*version=2 state=ESTABLISHED local-host=10.1.0.10 local-port=4500 local-id=alice at strongswan.org remote-host=192.168.0.2 remote-port=4500 remote-id=sun.strongswan.org initiator=yes.*nat-local=yes nat-any=yes encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.3.0.1] child-sas.*nat-t.*state=INSTALLED mode=TUNNEL protocol=ESP encap=yes.*encr-alg=AES_CBC encr-keysize=12 [...]
+venus::swanctl --list-sas --raw 2> /dev/null::nat-t.*version=2 state=ESTABLISHED local-host=10.1.0.20 local-port=4500 local-id=venus.strongswan.org remote-host=192.168.0.2 remote-port=4500 remote-id=sun.strongswan.org initiator=yes.*nat-local=yes nat-any=yes encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.3.0.2] child-sas.*nat-t.*state=INSTALLED mode=TUNNEL protocol=ESP encap=yes.*encr-alg=AES_CBC encr-keysize=12 [...]
+sun::swanctl --list-sas --ike-id 1 --raw 2> /dev/null::nat-t.*version=2 state=ESTABLISHED local-host=192.168.0.2
+ local-port=4500 local-id=sun.strongswan.org remote-host=192.168.0.1.*remote-id=alice at strongswan.org.*nat-remote=yes nat-any=yes encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.3.0.1] child-sas.*nat-t.*state=INSTALLED mode=TUNNEL protocol=ESP encap=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[0.0.0.0/0] remote-ts=\[10.3.0.1/32]::YES
+sun::swanctl --list-sas --ike-id 2 --raw 2> /dev/null::nat-t.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=4500 local-id=sun.strongswan.org remote-host=192.168.0.1.*remote-id=venus.strongswan.org.*nat-remote=yes nat-any=yes encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.3.0.2] child-sas.*nat-t.*state=INSTALLED mode=TUNNEL protocol=ESP encap=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_ [...]
 moon::tcpdump::IP moon.strongswan.org.* > sun.strongswan.org.4500: UDP-encap: ESP::YES
 moon::tcpdump::IP sun.strongswan.org.4500 > moon.strongswan.org.*: UDP-encap: ESP::YES
 alice::tcpdump::IP alice.strongswan.org > venus.strongswan.org: ICMP::YES
-alice::tcpdump::IP venus.strongswan.org > alice.strongswan.org: ICMP::YES
\ No newline at end of file
+alice::tcpdump::IP venus.strongswan.org > alice.strongswan.org: ICMP::YES
diff --git a/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/ipsec.conf b/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/ipsec.conf
deleted file mode 100644
index 50eccad..0000000
--- a/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/ipsec.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-# configuration is read from SQLite database
diff --git a/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/ipsec.secrets b/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/ipsec.secrets
deleted file mode 100644
index 76bb21b..0000000
--- a/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-# secrets are read from SQLite database
diff --git a/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/strongswan.conf b/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/strongswan.conf
index f4dd8f1..209df58 100644
--- a/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/strongswan.conf
+++ b/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/strongswan.conf
@@ -6,7 +6,7 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 
   keep_alive = 5
 }
diff --git a/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/swanctl/swanctl.conf b/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/ipsec.conf b/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/ipsec.conf
deleted file mode 100644
index 50eccad..0000000
--- a/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/ipsec.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-# configuration is read from SQLite database
diff --git a/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/ipsec.d/data.sql b/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/ipsec.d/data.sql
index 8489f10..abda7ca 100644
--- a/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/ipsec.d/data.sql
@@ -117,7 +117,7 @@ INSERT INTO peer_configs (
 INSERT INTO child_configs (
   name, updown
 ) VALUES (
-  'nat-t', 'ipsec _updown iptables'
+  'nat-t', '/usr/local/libexec/ipsec/_updown iptables'
 );
 
 INSERT INTO peer_config_child_config (
diff --git a/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/ipsec.secrets b/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/ipsec.secrets
deleted file mode 100644
index 76bb21b..0000000
--- a/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-# secrets are read from SQLite database
diff --git a/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/strongswan.conf b/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/strongswan.conf
index 6210c21..4048545 100644
--- a/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/strongswan.conf
+++ b/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/strongswan.conf
@@ -9,5 +9,5 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql attr-sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql attr-sql
 }
diff --git a/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/swanctl/swanctl.conf b/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/ipsec.conf b/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/ipsec.conf
deleted file mode 100644
index 50eccad..0000000
--- a/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/ipsec.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-# configuration is read from SQLite database
diff --git a/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/ipsec.secrets b/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/ipsec.secrets
deleted file mode 100644
index 76bb21b..0000000
--- a/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-# secrets are read from SQLite database
diff --git a/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/strongswan.conf b/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/strongswan.conf
index f4dd8f1..209df58 100644
--- a/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/strongswan.conf
+++ b/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/strongswan.conf
@@ -6,7 +6,7 @@ charon {
       database = sqlite:///etc/db.d/ipsec.db
     }
   }
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown sqlite sql
 
   keep_alive = 5
 }
diff --git a/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/swanctl/swanctl.conf b/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6b56173
--- /dev/null
+++ b/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# configuration is read from SQLite database
diff --git a/testing/tests/sql/shunt-policies-nat-rw/posttest.dat b/testing/tests/sql/shunt-policies-nat-rw/posttest.dat
index e772be6..b02b193 100644
--- a/testing/tests/sql/shunt-policies-nat-rw/posttest.dat
+++ b/testing/tests/sql/shunt-policies-nat-rw/posttest.dat
@@ -1,5 +1,5 @@
-sun::ipsec stop
-alice::ipsec stop
-venus::ipsec stop
+alice::service charon stop 2> /dev/null
+venus::service charon stop 2> /dev/null
+sun::service charon stop 2> /dev/null
 sun::iptables-restore < /etc/iptables.flush
-moon::iptables -t nat -F
\ No newline at end of file
+moon::iptables -t nat -F
diff --git a/testing/tests/sql/shunt-policies-nat-rw/pretest.dat b/testing/tests/sql/shunt-policies-nat-rw/pretest.dat
index c23c099..8d61e4c 100644
--- a/testing/tests/sql/shunt-policies-nat-rw/pretest.dat
+++ b/testing/tests/sql/shunt-policies-nat-rw/pretest.dat
@@ -1,6 +1,3 @@
-alice::rm /etc/ipsec.d/cacerts/*
-venus::rm /etc/ipsec.d/cacerts/*
-sun::rm /etc/ipsec.d/cacerts/*
 alice::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 venus::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
 sun::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/db.d/ipsec.sql
@@ -10,11 +7,11 @@ sun::cat /etc/db.d/ipsec.sql | sqlite3 /etc/db.d/ipsec.db
 sun::iptables-restore < /etc/iptables.rules
 moon::iptables -t nat -A POSTROUTING -o eth0 -s 10.1.0.0/16 -p udp -j SNAT --to-source PH_IP_MOON:1024-1100
 moon::iptables -t nat -A POSTROUTING -o eth0 -s 10.1.0.0/16 -p tcp -j SNAT --to-source PH_IP_MOON:2000-2100
-alice::ipsec start
-venus::ipsec start
-sun::ipsec start
+sun::service charon start 2> /dev/null
+alice::service charon start 2> /dev/null
+venus::service charon start 2> /dev/null
+sun::expect-connection nat-t
 alice::expect-connection nat-t
+alice::swanctl --initiate --child nat-t 2> /dev/null
 venus::expect-connection nat-t
-sun::expect-connection nat-t
-alice::ipsec up nat-t
-venus::ipsec up nat-t
\ No newline at end of file
+venus::swanctl --initiate --child nat-t 2> /dev/null
diff --git a/testing/tests/sql/shunt-policies-nat-rw/test.conf b/testing/tests/sql/shunt-policies-nat-rw/test.conf
index d797acb..d22f206 100644
--- a/testing/tests/sql/shunt-policies-nat-rw/test.conf
+++ b/testing/tests/sql/shunt-policies-nat-rw/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="alice venus sun"
 # Guest instances on which databases are used
 #
 DBHOSTS="alice venus sun"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/swanctl/config-payload/description.txt b/testing/tests/swanctl/config-payload/description.txt
new file mode 100755
index 0000000..3e68a77
--- /dev/null
+++ b/testing/tests/swanctl/config-payload/description.txt
@@ -0,0 +1,8 @@
+The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each to gateway <b>moon</b>.
+Both <b>carol</b> and <b>dave</b> request a <b>virtual IP</b> via the IKEv2 configuration payload.
+<b>moon</b> explicitly assigns a specific virtual IP to each of the two clients.
+<p/>
+<b>leftfirewall=yes</b> automatically inserts iptables-based firewall rules that let pass the
+tunneled traffic. In order to test the tunnels, <b>carol</b> and <b>dave</b> then ping the client
+<b>alice</b> behind the gateway <b>moon</b>. The source IP addresses of the two pings will be the
+virtual IPs <b>10.3.0.1</b> and <b>10.3.0.2</b>, respectively.
diff --git a/testing/tests/swanctl/config-payload/evaltest.dat b/testing/tests/swanctl/config-payload/evaltest.dat
new file mode 100755
index 0000000..7d55844
--- /dev/null
+++ b/testing/tests/swanctl/config-payload/evaltest.dat
@@ -0,0 +1,16 @@
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.3.0.1/32] remote-ts=\[10.1.0.0/16]::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.3.0.2/32] remote-ts=\[10.1.0.0/16]::YES
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.3.0.1/32]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.3.0.2/32]
+moon:: swanctl --list-pools --raw --leases 2> /dev/null::address=10.3.0.1 identity=carol at strongswan.org status=online::YES
+moon:: swanctl --list-pools --raw --leases 2> /dev/null::address=10.3.0.2 identity=dave at strongswan.org status=online::YES
+moon:: cat /var/log/daemon.log::assigning virtual IP 10.3.0.1 to peer.*carol at strongswan.org::YES
+moon:: cat /var/log/daemon.log::assigning virtual IP 10.3.0.2 to peer.*dave at strongswan.org::YES
+carol::cat /var/log/daemon.log::installing new virtual IP 10.3.0.1::YES
+dave:: cat /var/log/daemon.log::installing new virtual IP 10.3.0.2::YES
+alice::ping -c 1 10.3.0.1::64 bytes from 10.3.0.1: icmp_req=1::YES
+alice::ping -c 1 10.3.0.2::64 bytes from 10.3.0.2: icmp_req=1::YES
+moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
+moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
+moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES
+moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/swanctl/config-payload/hosts/carol/etc/strongswan.conf b/testing/tests/swanctl/config-payload/hosts/carol/etc/strongswan.conf
new file mode 100755
index 0000000..7d7e5f9
--- /dev/null
+++ b/testing/tests/swanctl/config-payload/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,14 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 x509 revocation constraints pubkey openssl random 
+}
+
+charon {
+  load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints pubkey gmp random nonce curl kernel-netlink socket-default updown vici 
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/config-payload/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/config-payload/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..f1a76db
--- /dev/null
+++ b/testing/tests/swanctl/config-payload/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,28 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+      vips = 0.0.0.0 
+
+      local {
+         auth = pubkey
+         certs = carolCert.pem
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/swanctl/config-payload/hosts/dave/etc/strongswan.conf b/testing/tests/swanctl/config-payload/hosts/dave/etc/strongswan.conf
new file mode 100755
index 0000000..7d7e5f9
--- /dev/null
+++ b/testing/tests/swanctl/config-payload/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,14 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 x509 revocation constraints pubkey openssl random 
+}
+
+charon {
+  load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints pubkey gmp random nonce curl kernel-netlink socket-default updown vici 
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/config-payload/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/config-payload/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..184185b
--- /dev/null
+++ b/testing/tests/swanctl/config-payload/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,28 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+      vips = 0.0.0.0 
+
+      local {
+         auth = pubkey
+         certs = daveCert.pem
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/swanctl/config-payload/hosts/moon/etc/strongswan.conf b/testing/tests/swanctl/config-payload/hosts/moon/etc/strongswan.conf
new file mode 100755
index 0000000..cd161be
--- /dev/null
+++ b/testing/tests/swanctl/config-payload/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,15 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 x509 revocation constraints pubkey openssl random 
+}
+
+charon {
+  load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints pubkey gmp random nonce curl kernel-netlink socket-default updown vici 
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds
+    pools = /usr/local/sbin/swanctl --load-pools 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/config-payload/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/config-payload/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..5b4f021
--- /dev/null
+++ b/testing/tests/swanctl/config-payload/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,34 @@
+connections {
+
+   rw-carol {
+      include swanctl_base.conf
+      pools = carol_vip
+
+      remote {
+         auth = pubkey
+         id = carol at strongswan.org
+      }
+   }
+
+   rw-dave {
+      include swanctl_base.conf
+      pools = dave_vip
+
+      remote {
+         auth = pubkey
+         id = dave at strongswan.org
+      }
+   }
+
+}
+
+pools {
+
+   carol_vip {
+      addrs = 10.3.0.1
+   }
+
+   dave_vip {
+      addrs = 10.3.0.2
+   }
+}
diff --git a/testing/tests/swanctl/config-payload/hosts/moon/etc/swanctl/swanctl_base.conf b/testing/tests/swanctl/config-payload/hosts/moon/etc/swanctl/swanctl_base.conf
new file mode 100755
index 0000000..08fa711
--- /dev/null
+++ b/testing/tests/swanctl/config-payload/hosts/moon/etc/swanctl/swanctl_base.conf
@@ -0,0 +1,17 @@
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey
+         certs = moonCert.pem
+         id = moon.strongswan.org
+      }
+      children {
+         net {
+            local_ts  = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
diff --git a/testing/tests/swanctl/config-payload/posttest.dat b/testing/tests/swanctl/config-payload/posttest.dat
new file mode 100755
index 0000000..d7107cc
--- /dev/null
+++ b/testing/tests/swanctl/config-payload/posttest.dat
@@ -0,0 +1,8 @@
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
+moon::iptables-restore < /etc/iptables.flush
+carol::iptables-restore < /etc/iptables.flush
+dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/swanctl/config-payload/pretest.dat b/testing/tests/swanctl/config-payload/pretest.dat
new file mode 100755
index 0000000..9c281d0
--- /dev/null
+++ b/testing/tests/swanctl/config-payload/pretest.dat
@@ -0,0 +1,12 @@
+moon::iptables-restore < /etc/iptables.rules
+carol::iptables-restore < /etc/iptables.rules
+dave::iptables-restore < /etc/iptables.rules
+moon::cat /etc/swanctl/swanctl_base.conf
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw-carol
+carol::expect-connection home
+carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/config-payload/test.conf b/testing/tests/swanctl/config-payload/test.conf
new file mode 100755
index 0000000..1227b9d
--- /dev/null
+++ b/testing/tests/swanctl/config-payload/test.conf
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# guest instances used for this test
+
+# All guest instances that are required for this test
+#
+VIRTHOSTS="alice moon carol winnetou dave"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-m-c-w-d.png"
+
+# Guest instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="moon"
+
+# Guest instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon carol dave"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/swanctl/dhcp-dynamic/description.txt b/testing/tests/swanctl/dhcp-dynamic/description.txt
new file mode 100644
index 0000000..bef5423
--- /dev/null
+++ b/testing/tests/swanctl/dhcp-dynamic/description.txt
@@ -0,0 +1,8 @@
+The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each to gateway <b>moon</b>
+and request a <b>virtual IP</b> via the IKEv2 configuration payload by using the <b>vips=0.0.0.0</b>
+parameter. The <b>dhcp</b> plugin on gateway <b>moon</b> then requests an IP address and DNS server
+information from DHCP server <b>venus</b> using the DHCP protocol. The IP addresses are assigned dynamically
+by <b>venus</b> from the pool 10.1.0.50..10.1.0.60 so that <b>carol</b> and <b>dave</b> become full members
+of the subnet 10.1.0.0/16 hidden behind gateway <b>moon</b>. And this thanks to the <b>farp</b> plugin
+through which <b>moon</b> acts as a proxy for ARP requests e.g. from <b>alice</b> who wants to ping
+<b>carol</b> and <b>dave</b>. 
diff --git a/testing/tests/swanctl/dhcp-dynamic/evaltest.dat b/testing/tests/swanctl/dhcp-dynamic/evaltest.dat
new file mode 100644
index 0000000..74d6ca8
--- /dev/null
+++ b/testing/tests/swanctl/dhcp-dynamic/evaltest.dat
@@ -0,0 +1,22 @@
+alice::ping -c 1 10.1.0.50::64 bytes from 10.1.0.50: icmp_req=1::YES
+carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+alice::ping -c 1 10.1.0.51::64 bytes from 10.1.0.51: icmp_req=1::YES
+dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.1.0.50] child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.50/32] remote-ts [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.1.0.51] child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.51/32] remote-ts= [...]
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.1.0.50] child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote- [...]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.1.0.51] child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-t [...]
+moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
+moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
+moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
+moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES
+alice::tcpdump::ARP, Reply carol3.strongswan.org is-at 52:54:00:43:e3:35::YES
+alice::tcpdump::IP alice.strongswan.org > carol3.strongswan.org: ICMP echo request::YES
+alice::tcpdump::IP carol3.strongswan.org > alice.strongswan.org: ICMP echo reply::YES
+alice::tcpdump::IP carol3.strongswan.org > alice.strongswan.org: ICMP echo request::YES
+alice::tcpdump::IP alice.strongswan.org > carol3.strongswan.org: ICMP echo reply::YES
+alice::tcpdump::ARP, Reply dave3.strongswan.org is-at 52:54:00:43:e3:35::YES
+alice::tcpdump::IP alice.strongswan.org > dave3.strongswan.org: ICMP echo request::YES
+alice::tcpdump::IP dave3.strongswan.org > alice.strongswan.org: ICMP echo reply::YES
+alice::tcpdump::IP dave3.strongswan.org > alice.strongswan.org: ICMP echo request::YES
+alice::tcpdump::IP alice.strongswan.org > dave3.strongswan.org: ICMP echo reply::YES
diff --git a/testing/tests/swanctl/dhcp-dynamic/hosts/carol/etc/strongswan.conf b/testing/tests/swanctl/dhcp-dynamic/hosts/carol/etc/strongswan.conf
new file mode 100755
index 0000000..5b06b25
--- /dev/null
+++ b/testing/tests/swanctl/dhcp-dynamic/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,14 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 x509 revocation constraints pubkey openssl random 
+}
+
+charon {
+  load = random nonce sha1 sha2 aes hmac pem pkcs1 x509 revocation constraints pubkey gmp curl kernel-netlink socket-default resolve updown vici
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/dhcp-dynamic/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/dhcp-dynamic/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..f1a76db
--- /dev/null
+++ b/testing/tests/swanctl/dhcp-dynamic/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,28 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+      vips = 0.0.0.0 
+
+      local {
+         auth = pubkey
+         certs = carolCert.pem
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/swanctl/dhcp-dynamic/hosts/dave/etc/strongswan.conf b/testing/tests/swanctl/dhcp-dynamic/hosts/dave/etc/strongswan.conf
new file mode 100755
index 0000000..5b06b25
--- /dev/null
+++ b/testing/tests/swanctl/dhcp-dynamic/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,14 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 x509 revocation constraints pubkey openssl random 
+}
+
+charon {
+  load = random nonce sha1 sha2 aes hmac pem pkcs1 x509 revocation constraints pubkey gmp curl kernel-netlink socket-default resolve updown vici
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/dhcp-dynamic/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/dhcp-dynamic/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..184185b
--- /dev/null
+++ b/testing/tests/swanctl/dhcp-dynamic/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,28 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+      vips = 0.0.0.0 
+
+      local {
+         auth = pubkey
+         certs = daveCert.pem
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/swanctl/dhcp-dynamic/hosts/moon/etc/dhcpd.conf b/testing/tests/swanctl/dhcp-dynamic/hosts/moon/etc/dhcpd.conf
new file mode 100644
index 0000000..0340d56
--- /dev/null
+++ b/testing/tests/swanctl/dhcp-dynamic/hosts/moon/etc/dhcpd.conf
@@ -0,0 +1,9 @@
+subnet 10.1.0.0 netmask 255.255.0.0 {
+  option routers 10.1.0.1;
+  option broadcast-address 10.1.255.255;
+  option domain-name servers PH_IP_WINNETOU PH_IP_VENUS
+  option netbios-name-servers PH_IP_VENUS;
+
+  # dynamic address pool for visitors
+  range 10.1.0.30 10.1.0.50;
+}
diff --git a/testing/tests/swanctl/dhcp-dynamic/hosts/moon/etc/iptables.rules b/testing/tests/swanctl/dhcp-dynamic/hosts/moon/etc/iptables.rules
new file mode 100644
index 0000000..2d9a466
--- /dev/null
+++ b/testing/tests/swanctl/dhcp-dynamic/hosts/moon/etc/iptables.rules
@@ -0,0 +1,39 @@
+*filter
+
+# default policy is DROP
+-P INPUT DROP
+-P OUTPUT DROP
+-P FORWARD DROP
+
+# allow bootpc and bootps
+-A OUTPUT -p udp --sport bootpc --dport bootps -j ACCEPT
+-A INPUT  -p udp --sport bootps --dport bootps -j ACCEPT
+
+# allow broadcasts from eth1
+-A INPUT -i eth1 -d 10.1.255.255 -j ACCEPT
+
+# allow esp
+-A INPUT  -i eth0 -p 50 -j ACCEPT
+-A OUTPUT -o eth0 -p 50 -j ACCEPT
+
+# allow IKE
+-A INPUT  -i eth0 -p udp --sport 500 --dport 500 -j ACCEPT
+-A OUTPUT -o eth0 -p udp --dport 500 --sport 500 -j ACCEPT
+
+# allow MobIKE
+-A INPUT  -i eth0 -p udp --sport 4500 --dport 4500 -j ACCEPT
+-A OUTPUT -o eth0 -p udp --dport 4500 --sport 4500 -j ACCEPT
+
+# allow ssh
+-A INPUT  -p tcp --dport 22 -j ACCEPT
+-A OUTPUT -p tcp --sport 22 -j ACCEPT
+
+# allow crl fetch from winnetou
+-A INPUT  -i eth0 -p tcp --sport 80 -s PH_IP_WINNETOU -j ACCEPT
+-A OUTPUT -o eth0 -p tcp --dport 80 -d PH_IP_WINNETOU -j ACCEPT
+
+# log dropped packets
+-A INPUT  -j LOG --log-prefix " IN: "
+-A OUTPUT -j LOG --log-prefix " OUT: "
+
+COMMIT
diff --git a/testing/tests/swanctl/dhcp-dynamic/hosts/moon/etc/strongswan.conf b/testing/tests/swanctl/dhcp-dynamic/hosts/moon/etc/strongswan.conf
new file mode 100755
index 0000000..36e4e77
--- /dev/null
+++ b/testing/tests/swanctl/dhcp-dynamic/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,20 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 x509 revocation constraints pubkey openssl random
+}
+
+charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown attr farp dhcp
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+
+  plugins {
+    dhcp {
+      server = 10.1.255.255
+    }
+  }
+}
diff --git a/testing/tests/swanctl/dhcp-dynamic/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/dhcp-dynamic/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..e19568b
--- /dev/null
+++ b/testing/tests/swanctl/dhcp-dynamic/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,26 @@
+connections {
+
+   rw {
+      local_addrs  = 192.168.0.1
+      pools = dhcp
+
+      local {
+         auth = pubkey
+         certs = moonCert.pem
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = pubkey
+      }
+      children {
+         net {
+            local_ts  = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/swanctl/dhcp-dynamic/hosts/venus/etc/dhcp/dhcpd.conf b/testing/tests/swanctl/dhcp-dynamic/hosts/venus/etc/dhcp/dhcpd.conf
new file mode 100644
index 0000000..7a17850
--- /dev/null
+++ b/testing/tests/swanctl/dhcp-dynamic/hosts/venus/etc/dhcp/dhcpd.conf
@@ -0,0 +1,14 @@
+# dhcpd configuration file
+
+ddns-update-style none;
+
+subnet 10.1.0.0 netmask 255.255.0.0 {
+  option domain-name          "strongswan.org";
+  option domain-name-servers   PH_IP_VENUS;
+  option netbios-name-servers  PH_IP_ALICE;
+  option routers               PH_IP_MOON1;
+  option broadcast-address     10.1.255.255;
+  next-server                  PH_IP_VENUS;
+
+  range 10.1.0.50 10.1.0.60;
+}
diff --git a/testing/tests/swanctl/dhcp-dynamic/hosts/venus/etc/dnsmasq.conf b/testing/tests/swanctl/dhcp-dynamic/hosts/venus/etc/dnsmasq.conf
new file mode 100644
index 0000000..ec8c945
--- /dev/null
+++ b/testing/tests/swanctl/dhcp-dynamic/hosts/venus/etc/dnsmasq.conf
@@ -0,0 +1,7 @@
+interface=eth0
+dhcp-range=10.1.0.50,10.1.0.60,255.255.0.0,10.1.255.255
+dhcp-option=option:router,PH_IP_MOON1
+dhcp-option=option:dns-server,PH_IP_VENUS
+dhcp-option=option:netbios-ns,PH_IP_ALICE
+dhcp-option=option:domain-name,strongswan.org
+log-dhcp
diff --git a/testing/tests/swanctl/dhcp-dynamic/posttest.dat b/testing/tests/swanctl/dhcp-dynamic/posttest.dat
new file mode 100644
index 0000000..624a26b
--- /dev/null
+++ b/testing/tests/swanctl/dhcp-dynamic/posttest.dat
@@ -0,0 +1,12 @@
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
+venus::cat /var/state/dhcp/dhcpd.leases
+venus::/etc/init.d/isc-dhcp-server stop 2> /dev/null
+moon::iptables-restore < /etc/iptables.flush
+carol::iptables-restore < /etc/iptables.flush
+dave::iptables-restore < /etc/iptables.flush
+alice::arp -d 10.1.0.50
+alice::arp -d 10.1.0.51
diff --git a/testing/tests/swanctl/dhcp-dynamic/pretest.dat b/testing/tests/swanctl/dhcp-dynamic/pretest.dat
new file mode 100644
index 0000000..6d935b6
--- /dev/null
+++ b/testing/tests/swanctl/dhcp-dynamic/pretest.dat
@@ -0,0 +1,13 @@
+moon::iptables-restore < /etc/iptables.rules
+carol::iptables-restore < /etc/iptables.rules
+dave::iptables-restore < /etc/iptables.rules
+venus::cat /etc/dhcp/dhcpd.conf
+venus::/etc/init.d/isc-dhcp-server start 2> /dev/null
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
+carol::expect-connection home
+carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/dhcp-dynamic/test.conf b/testing/tests/swanctl/dhcp-dynamic/test.conf
new file mode 100644
index 0000000..853093c
--- /dev/null
+++ b/testing/tests/swanctl/dhcp-dynamic/test.conf
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# guest instances used for this test
+
+# All guest instances that are required for this test
+#
+VIRTHOSTS="alice venus moon carol winnetou dave"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-v-m-c-w-d.png"
+
+# Guest instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="moon alice"
+
+# Guest instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon carol dave"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/swanctl/frags-ipv4/description.txt b/testing/tests/swanctl/frags-ipv4/description.txt
index 51744cf..b5b8711 100755
--- a/testing/tests/swanctl/frags-ipv4/description.txt
+++ b/testing/tests/swanctl/frags-ipv4/description.txt
@@ -1,7 +1,7 @@
-The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each 
-to gateway <b>moon</b> using the <b>IKEv2</b> key exchange protocol. The
-authentication is based on <b>X.509 certificates</b>. <b>dave</b> advertises 
-the support of the IKEv2 fragmentation protocol defined in <b>RFC 7383</b> 
+The roadwarriors <b>carol</b> and <b>dave</b> set up an IPv4 connection each to
+gateway <b>moon</b> using the <b>IKEv1</b> and <b>IKEv2</b> key exchange protocol,
+respectively. The authentication is based on <b>X.509 certificates</b>. <b>dave</b>
+advertises the support of the IKEv2 fragmentation protocol defined in <b>RFC 7383</b> 
 which prevents the IP fragmentation of the IKEv2 messages carrying large X.509 
 certificates whereas <b>carol</b> announces support of non-standardized
 IKEv1 fragmentation.
diff --git a/testing/tests/swanctl/frags-ipv4/evaltest.dat b/testing/tests/swanctl/frags-ipv4/evaltest.dat
index a4aea93..af4c5a0 100755
--- a/testing/tests/swanctl/frags-ipv4/evaltest.dat
+++ b/testing/tests/swanctl/frags-ipv4/evaltest.dat
@@ -7,10 +7,10 @@ dave:: cat /var/log/daemon.log::received fragment #1 of 2, waiting for complete
 dave:: cat /var/log/daemon.log::received fragment #2 of 2, reassembling fragmented IKE message::YES
 moon:: cat /var/log/daemon.log::received fragment #1 of 2, waiting for complete IKE message::YES
 moon:: cat /var/log/daemon.log::received fragment #2 of 2, reassembling fragmented IKE message::YES
-carol::swanctl --list-sas --raw 2> /dev/null::home.*version=1 state=ESTABLISHED local-host=192.168.0.100 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/16]::YES
-dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.0/16]::YES
-moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=1 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]::YES
-moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=1 state=ESTABLISHED local-host=192.168.0.100 local-port=500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.100/32] remote-t [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.200/32] remote-ts [...]
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=1 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-ts=\ [...]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.0/16] remote-ts=\[ [...]
 alice::ping -c 1 192.168.0.100::64 bytes from 192.168.0.100: icmp_req=1::YES
 alice::ping -c 1 192.168.0.200::64 bytes from 192.168.0.200: icmp_req=1::YES
 moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
diff --git a/testing/tests/swanctl/frags-ipv4/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/frags-ipv4/hosts/carol/etc/swanctl/swanctl.conf
index 9062e65..6b01dfc 100755
--- a/testing/tests/swanctl/frags-ipv4/hosts/carol/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/frags-ipv4/hosts/carol/etc/swanctl/swanctl.conf
@@ -17,17 +17,12 @@ connections {
          home {
             remote_ts = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
             esp_proposals = aes128-sha256-ecp256
          }
       }
-
       version = 1 
       fragmentation = yes
-      reauth_time = 60m
-      rekey_time =  20m
       proposals = aes128-sha256-ecp256
    }
 }
diff --git a/testing/tests/swanctl/frags-ipv4/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/frags-ipv4/hosts/dave/etc/swanctl/swanctl.conf
index a4abc6f..e1d2487 100755
--- a/testing/tests/swanctl/frags-ipv4/hosts/dave/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/frags-ipv4/hosts/dave/etc/swanctl/swanctl.conf
@@ -17,18 +17,13 @@ connections {
          home {
             remote_ts = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m
             esp_proposals = aes128-sha256-ecp256
          }
       }
-
       version = 2
       mobike = no 
       fragmentation = yes 
-      reauth_time = 60m
-      rekey_time =  20m
       proposals = aes128-sha256-ecp256
    }
 }
diff --git a/testing/tests/swanctl/frags-ipv4/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/frags-ipv4/hosts/moon/etc/swanctl/swanctl.conf
index a19f542..2d219cd 100755
--- a/testing/tests/swanctl/frags-ipv4/hosts/moon/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/frags-ipv4/hosts/moon/etc/swanctl/swanctl.conf
@@ -15,17 +15,12 @@ connections {
          net {
             local_ts  = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
             esp_proposals = aes128-sha256-ecp256
          }
       }
-
       mobike = no
       fragmentation = yes
-      reauth_time = 60m
-      rekey_time =  20m
       proposals = aes128-sha256-ecp256
    }
 }
diff --git a/testing/tests/swanctl/frags-ipv4/pretest.dat b/testing/tests/swanctl/frags-ipv4/pretest.dat
index 706bd1e..762c354 100755
--- a/testing/tests/swanctl/frags-ipv4/pretest.dat
+++ b/testing/tests/swanctl/frags-ipv4/pretest.dat
@@ -4,6 +4,8 @@ dave::iptables-restore < /etc/iptables.rules
 moon::service charon start 2> /dev/null
 carol::service charon start 2> /dev/null
 dave::service charon start 2> /dev/null
-moon::sleep 1
+moon::expect-connection rw
+carol::expect-connection home
 carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
 dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/frags-ipv6/evaltest.dat b/testing/tests/swanctl/frags-ipv6/evaltest.dat
index 4ec34d7..18814f6 100755
--- a/testing/tests/swanctl/frags-ipv6/evaltest.dat
+++ b/testing/tests/swanctl/frags-ipv6/evaltest.dat
@@ -7,10 +7,10 @@ dave:: cat /var/log/daemon.log::received fragment #1 of 2, waiting for complete
 dave:: cat /var/log/daemon.log::received fragment #2 of 2, reassembling fragmented IKE message::YES
 moon:: cat /var/log/daemon.log::received fragment #1 of 2, waiting for complete IKE message::YES
 moon:: cat /var/log/daemon.log::received fragment #2 of 2, reassembling fragmented IKE message::YES
-carol::swanctl --list-sas --raw 2> /dev/null::home.*version=1 state=ESTABLISHED local-host=fec0:\:10 local-id=carol at strongswan.org remote-host=fec0:\:1 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[fec0:\:10/128] remote-ts=\[fec1:\:/16]::YES
-dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=fec0:\:20 local-id=dave at strongswan.org remote-host=fec0:\:1 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[fec0:\:20/128] remote-ts=\[fec1:\:/16]::YES
-moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=1 state=ESTABLISHED local-host=fec0:\:1 local-id=moon.strongswan.org remote-host=fec0:\:10 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[fec1:\:/16] remote-ts=\[fec0:\:10/128]::YES
-moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=fec0:\:1 local-id=moon.strongswan.org remote-host=fec0:\:20 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[fec1:\:/16] remote-ts=\[fec0:\:20/128]::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=1 state=ESTABLISHED local-host=fec0:\:10 local-port=500 local-id=carol at strongswan.org remote-host=fec0:\:1 remote-port=500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[fec0:\:10/128] remote-ts=\[fec1:\ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=fec0:\:20 local-port=500 local-id=dave at strongswan.org remote-host=fec0:\:1 remote-port=500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[fec0:\:20/128] remote-ts=\[fec1:\: [...]
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=1 state=ESTABLISHED local-host=fec0:\:1 local-port=500 local-id=moon.strongswan.org remote-host=fec0:\:10 remote-port=500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[fec1:\:/16] remote-ts=\[fec0:\: [...]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=fec0:\:1 local-port=500 local-id=moon.strongswan.org remote-host=fec0:\:20 remote-port=500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[fec1:\:/16] remote-ts=\[fec0:\:2 [...]
 alice::ping6 -c 1 ip6-carol.strongswan.org::64 bytes from ip6-carol.strongswan.org: icmp_seq=1::YES
 alice::ping6 -c 1 ip6-dave.strongswan.org::64 bytes from ip6-dave.strongswan.org: icmp_seq=1::YES
 moon::tcpdump::IP6 ip6-moon.strongswan.org > ip6-carol.strongswan.org: ESP::YES
diff --git a/testing/tests/swanctl/frags-ipv6/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/frags-ipv6/hosts/carol/etc/swanctl/swanctl.conf
index 9e857f6..71fc4ea 100755
--- a/testing/tests/swanctl/frags-ipv6/hosts/carol/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/frags-ipv6/hosts/carol/etc/swanctl/swanctl.conf
@@ -17,17 +17,12 @@ connections {
          home {
             remote_ts = fec1::/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
             esp_proposals = aes128-sha256-ecp256
          }
       }
-
       version = 1 
       fragmentation = yes
-      reauth_time = 60m
-      rekey_time =  20m
       proposals = aes128-sha256-ecp256
    }
 }
diff --git a/testing/tests/swanctl/frags-ipv6/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/frags-ipv6/hosts/dave/etc/swanctl/swanctl.conf
index bc5e541..f4e8a81 100755
--- a/testing/tests/swanctl/frags-ipv6/hosts/dave/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/frags-ipv6/hosts/dave/etc/swanctl/swanctl.conf
@@ -17,18 +17,13 @@ connections {
          home {
             remote_ts = fec1::/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m
             esp_proposals = aes128-sha256-ecp256
          }
       }
-
       version = 2
       mobike = no 
       fragmentation = yes 
-      reauth_time = 60m
-      rekey_time =  20m
       proposals = aes128-sha256-ecp256
    }
 }
diff --git a/testing/tests/swanctl/frags-ipv6/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/frags-ipv6/hosts/moon/etc/swanctl/swanctl.conf
index a59d137..a6241e9 100755
--- a/testing/tests/swanctl/frags-ipv6/hosts/moon/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/frags-ipv6/hosts/moon/etc/swanctl/swanctl.conf
@@ -15,17 +15,12 @@ connections {
          net {
             local_ts = fec1::/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
             esp_proposals = aes128-sha256-ecp256
          }
       }
-
       mobike = no
       fragmentation = yes
-      reauth_time = 60m
-      rekey_time =  20m
       proposals = aes128-sha256-ecp256
    }
 }
diff --git a/testing/tests/swanctl/frags-ipv6/pretest.dat b/testing/tests/swanctl/frags-ipv6/pretest.dat
index 8680386..9593ac9 100755
--- a/testing/tests/swanctl/frags-ipv6/pretest.dat
+++ b/testing/tests/swanctl/frags-ipv6/pretest.dat
@@ -10,6 +10,8 @@ dave::"ip route add fec1:\:/16 via fec0:\:1"
 moon::service charon start 2> /dev/null
 carol::service charon start 2> /dev/null
 dave::service charon start 2> /dev/null
-moon::sleep 1
+moon::expect-connection rw
+carol::expect-connection home
 carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
 dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/ip-pool-db/evaltest.dat b/testing/tests/swanctl/ip-pool-db/evaltest.dat
index f76c356..4af4f30 100755
--- a/testing/tests/swanctl/ip-pool-db/evaltest.dat
+++ b/testing/tests/swanctl/ip-pool-db/evaltest.dat
@@ -1,7 +1,7 @@
-carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.3.0.1/32] remote-ts=\[10.1.0.0/16]::YES
-dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.3.0.2/32] remote-ts=\[10.1.0.0/16]::YES
-moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.3.0.1/32]
-moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.3.0.2/32]
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.3.0.1/32] remote-ts=\[10.1.0.0/16]::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.3.0.2/32] remote-ts=\[10.1.0.0/16]::YES
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.3.0.1/32]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.3.0.2/32]
 moon:: cat /var/log/daemon.log::assigning virtual IP 10.3.0.1 to peer.*carol at strongswan.org::YES
 moon:: cat /var/log/daemon.log::assigning virtual IP 10.3.0.2 to peer.*dave at strongswan.org::YES
 moon:: ipsec pool --status 2> /dev/null::big_pool.*10.3.0.1.*10.3.3.232.*static.*2::YES
diff --git a/testing/tests/swanctl/ip-pool-db/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/ip-pool-db/hosts/carol/etc/swanctl/swanctl.conf
index 0bb3414..f1a76db 100755
--- a/testing/tests/swanctl/ip-pool-db/hosts/carol/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/ip-pool-db/hosts/carol/etc/swanctl/swanctl.conf
@@ -18,16 +18,11 @@ connections {
          home {
             remote_ts = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
diff --git a/testing/tests/swanctl/ip-pool-db/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/ip-pool-db/hosts/dave/etc/swanctl/swanctl.conf
index 24d2f86..184185b 100755
--- a/testing/tests/swanctl/ip-pool-db/hosts/dave/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/ip-pool-db/hosts/dave/etc/swanctl/swanctl.conf
@@ -18,16 +18,11 @@ connections {
          home {
             remote_ts = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
diff --git a/testing/tests/swanctl/ip-pool-db/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/ip-pool-db/hosts/moon/etc/swanctl/swanctl.conf
index d05dea0..3975512 100755
--- a/testing/tests/swanctl/ip-pool-db/hosts/moon/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/ip-pool-db/hosts/moon/etc/swanctl/swanctl.conf
@@ -16,16 +16,11 @@ connections {
          net {
             local_ts  = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
diff --git a/testing/tests/swanctl/ip-pool-db/pretest.dat b/testing/tests/swanctl/ip-pool-db/pretest.dat
index 91380e6..955a3c9 100755
--- a/testing/tests/swanctl/ip-pool-db/pretest.dat
+++ b/testing/tests/swanctl/ip-pool-db/pretest.dat
@@ -7,9 +7,11 @@ moon::ipsec pool --addattr nbns --server PH_IP_VENUS 2> /dev/null
 moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
 dave::iptables-restore < /etc/iptables.rules
-moon::service charon start 2> /dev/null 
+moon::service charon start 2> /dev/null
 carol::service charon start 2> /dev/null
 dave::service charon start 2> /dev/null
-moon::sleep 1
+moon::expect-connection rw
+carol::expect-connection home
 carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
 dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/ip-pool/evaltest.dat b/testing/tests/swanctl/ip-pool/evaltest.dat
index a0891c3..5ba0002 100755
--- a/testing/tests/swanctl/ip-pool/evaltest.dat
+++ b/testing/tests/swanctl/ip-pool/evaltest.dat
@@ -1,7 +1,7 @@
-carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.3.0.1/32] remote-ts=\[10.1.0.0/16]::YES
-dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.3.0.2/32] remote-ts=\[10.1.0.0/16]::YES
-moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.3.0.1/32]
-moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.3.0.2/32]
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.3.0.1/32] remote-ts=\[10.1.0.0/16]::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.3.0.2/32] remote-ts=\[10.1.0.0/16]::YES
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.3.0.1/32]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.3.0.2/32]
 moon:: swanctl --list-pools --raw 2> /dev/null::rw_pool.*base=10.3.0.0 size=14 online=2 offline=0::YES
 moon:: swanctl --list-pools --raw --leases 2> /dev/null::address=10.3.0.1 identity=carol at strongswan.org status=online::YES
 moon:: swanctl --list-pools --raw --leases 2> /dev/null::address=10.3.0.2 identity=dave at strongswan.org status=online::YES
diff --git a/testing/tests/swanctl/ip-pool/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/ip-pool/hosts/carol/etc/swanctl/swanctl.conf
index 0bb3414..f1a76db 100755
--- a/testing/tests/swanctl/ip-pool/hosts/carol/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/ip-pool/hosts/carol/etc/swanctl/swanctl.conf
@@ -18,16 +18,11 @@ connections {
          home {
             remote_ts = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
diff --git a/testing/tests/swanctl/ip-pool/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/ip-pool/hosts/dave/etc/swanctl/swanctl.conf
index 24d2f86..184185b 100755
--- a/testing/tests/swanctl/ip-pool/hosts/dave/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/ip-pool/hosts/dave/etc/swanctl/swanctl.conf
@@ -18,16 +18,11 @@ connections {
          home {
             remote_ts = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
diff --git a/testing/tests/swanctl/ip-pool/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/ip-pool/hosts/moon/etc/swanctl/swanctl.conf
index aa31d0f..8d4dd6b 100755
--- a/testing/tests/swanctl/ip-pool/hosts/moon/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/ip-pool/hosts/moon/etc/swanctl/swanctl.conf
@@ -16,17 +16,12 @@ connections {
          net {
             local_ts  = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
 
diff --git a/testing/tests/swanctl/ip-pool/pretest.dat b/testing/tests/swanctl/ip-pool/pretest.dat
index 706bd1e..762c354 100755
--- a/testing/tests/swanctl/ip-pool/pretest.dat
+++ b/testing/tests/swanctl/ip-pool/pretest.dat
@@ -4,6 +4,8 @@ dave::iptables-restore < /etc/iptables.rules
 moon::service charon start 2> /dev/null
 carol::service charon start 2> /dev/null
 dave::service charon start 2> /dev/null
-moon::sleep 1
+moon::expect-connection rw
+carol::expect-connection home
 carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
 dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/description.txt b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/description.txt
new file mode 100644
index 0000000..3641d09
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/description.txt
@@ -0,0 +1,17 @@
+The roadwarrior <b>carol</b> sets up a connection to gateway <b>moon</b>
+using multiple authentication exchanges (RFC 4739). In a first round 
+both <b>carol</b> and <b>moon</b> authenticate themselves by sending 
+an IKEv2 <b>RSA signature</b> accompanied by a certificate.
+<p>
+In a second round <b>carol</b> then uses the <i>Extensible Authentication Protocol</i>
+in association with a <i>GSM Subscriber Identity Module</i> (<b>EAP-SIM</b>) to
+authenticate herself against the remote RADIUS server <b>alice</b>. 
+In this scenario, triplets from the file <b>/etc/ipsec.d/triplets.dat</b>
+are used instead of a physical SIM card on the client <b>carol</b>.
+The gateway forwards all EAP messages to the RADIUS server <b>alice</b>
+which also uses a static triplets file.
+<p>
+The roadwarrior <b>dave</b> also uses multiple authentication and succeeds
+in the first round but sends wrong EAP-SIM triplets in the second round.
+As a consequence the radius server <b>alice</b> returns an <b>Access-Reject</b>
+message and the gateway <b>moon</b> sends back an <b>EAP_FAILURE</b>. 	
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/evaltest.dat b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/evaltest.dat
new file mode 100644
index 0000000..50128d5
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/evaltest.dat
@@ -0,0 +1,20 @@
+moon:: cat /var/log/daemon.log::parsed IKE_AUTH request.*N(AUTH_FOLLOWS)::YES
+moon:: cat /var/log/daemon.log::authentication of .*carol at strongswan.org.* with RSA.* successful::YES
+carol::cat /var/log/daemon.log::authentication of .*moon.strongswan.org.* with RSA.* successful::YES
+carol::cat /var/log/daemon.log::server requested EAP_SIM authentication::YES
+moon:: cat /var/log/daemon.log::received EAP identity .*228060123456001::YES
+moon:: cat /var/log/daemon.log::authentication of .*228060123456001 at strongswan.org.* with EAP successful::YES
+carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=228060123456001 at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\ [...]
+moon::swanctl --list-sas --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=228060123456001 at strongswan.org remote-eap-id=228060123456001.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remo [...]
+moon::cat /var/log/daemon.log::authentication of .*dave at strongswan.org.* with RSA.* successful::YES
+dave::cat /var/log/daemon.log::authentication of .*moon.strongswan.org.* with RSA.* successful::YES
+dave::cat /var/log/daemon.log::server requested EAP_SIM authentication::YES
+moon::cat /var/log/daemon.log::received EAP identity .*228060123456002::YES
+moon::cat /var/log/daemon.log::RADIUS authentication of '228060123456002' failed::YES
+moon::cat /var/log/daemon.log::EAP method EAP_SIM failed for peer 228060123456002 at strongswan.org::YES
+dave::cat /var/log/daemon.log::received EAP_FAILURE, EAP authentication failed::YES
+dave::ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
+moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
+moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
+
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/alice/etc/freeradius/eap.conf b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/alice/etc/freeradius/eap.conf
new file mode 100644
index 0000000..7d80239
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/alice/etc/freeradius/eap.conf
@@ -0,0 +1,5 @@
+eap {
+  default_eap_type = sim
+  sim {
+  }
+}
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/alice/etc/freeradius/modules/sim_files b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/alice/etc/freeradius/modules/sim_files
new file mode 100644
index 0000000..10c26aa
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/alice/etc/freeradius/modules/sim_files
@@ -0,0 +1,3 @@
+sim_files {
+	simtriplets = "/etc/freeradius/triplets.dat"
+}
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/alice/etc/freeradius/proxy.conf b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/alice/etc/freeradius/proxy.conf
new file mode 100644
index 0000000..23cba8d
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/alice/etc/freeradius/proxy.conf
@@ -0,0 +1,5 @@
+realm strongswan.org {
+  type     = radius
+  authhost = LOCAL
+  accthost = LOCAL
+}
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/alice/etc/freeradius/sites-available/default b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/alice/etc/freeradius/sites-available/default
new file mode 100644
index 0000000..91425f8
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/alice/etc/freeradius/sites-available/default
@@ -0,0 +1,61 @@
+authorize {
+  preprocess
+  chap
+  mschap
+  sim_files
+  suffix
+  eap {
+    ok = return
+  }
+  unix
+  files
+  expiration
+  logintime
+  pap
+}
+
+authenticate {
+  Auth-Type PAP {
+    pap
+  }
+  Auth-Type CHAP {
+    chap
+  }
+  Auth-Type MS-CHAP {
+    mschap
+  }
+  unix
+  eap
+}
+
+preacct {
+  preprocess
+  acct_unique
+  suffix
+  files
+}
+
+accounting {
+  detail
+  unix
+  radutmp
+  attr_filter.accounting_response
+}
+
+session {
+  radutmp
+}
+
+post-auth {
+  exec
+  Post-Auth-Type REJECT {
+    attr_filter.access_reject
+  }
+}
+
+pre-proxy {
+}
+
+post-proxy {
+  eap
+}
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/alice/etc/freeradius/triplets.dat b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/alice/etc/freeradius/triplets.dat
new file mode 100644
index 0000000..aaabab8
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/alice/etc/freeradius/triplets.dat
@@ -0,0 +1,6 @@
+228060123456001,30000000000000000000000000000000,30112233,305566778899AABB
+228060123456001,31000000000000000000000000000000,31112233,315566778899AABB
+228060123456001,32000000000000000000000000000000,32112233,325566778899AABB
+228060123456002,33000000000000000000000000000000,33112233,335566778899AABB
+228060123456002,34000000000000000000000000000000,34112233,345566778899AABB
+228060123456002,35000000000000000000000000000000,35112233,355566778899AABB
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/alice/etc/freeradius/users b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/alice/etc/freeradius/users
new file mode 100644
index 0000000..e69de29
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/carol/etc/ipsec.d/triplets.dat b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/carol/etc/ipsec.d/triplets.dat
new file mode 100644
index 0000000..c167ba9
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/carol/etc/ipsec.d/triplets.dat
@@ -0,0 +1,3 @@
+228060123456001,30000000000000000000000000000000,30112233,305566778899AABB
+228060123456001,31000000000000000000000000000000,31112233,315566778899AABB
+228060123456001,32000000000000000000000000000000,32112233,325566778899AABB
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/carol/etc/strongswan.conf b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/carol/etc/strongswan.conf
new file mode 100644
index 0000000..bccbe5a
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,10 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac xcbc vici kernel-netlink socket-default fips-prf eap-sim eap-sim-file eap-identity updown
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..944e78e
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,32 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = pubkey
+         certs = carolCert.pem
+         id = carol at strongswan.org
+      }
+      local-eap {
+         auth = eap
+         id = 228060123456001 at strongswan.org
+         eap_id = 228060123456001 
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/dave/etc/ipsec.d/triplets.dat b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/dave/etc/ipsec.d/triplets.dat
new file mode 100644
index 0000000..b8b86c8
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/dave/etc/ipsec.d/triplets.dat
@@ -0,0 +1,3 @@
+228060123456002,33000000000000000000000000000000,33112244,335566778899AABB
+228060123456002,34000000000000000000000000000000,34112244,345566778899AABB
+228060123456002,35000000000000000000000000000000,35112244,355566778899AABB
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/dave/etc/strongswan.conf b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/dave/etc/strongswan.conf
new file mode 100644
index 0000000..bccbe5a
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,10 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac xcbc vici kernel-netlink socket-default fips-prf eap-sim eap-sim-file eap-identity updown
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..bca5ad3
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,32 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = pubkey
+         certs = daveCert.pem
+         id = dave at strongswan.org
+      }
+      local-eap {
+         auth = eap
+         id=228060123456002 at strongswan.org
+         eap_id=228060123456002
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/tnc/tnccs-11-supplicant/hosts/moon/etc/iptables.rules b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/moon/etc/iptables.rules
similarity index 100%
rename from testing/tests/tnc/tnccs-11-supplicant/hosts/moon/etc/iptables.rules
rename to testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/moon/etc/iptables.rules
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/moon/etc/strongswan.conf b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/moon/etc/strongswan.conf
new file mode 100644
index 0000000..7f90207
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,17 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp x509 curl revocation hmac xcbc vici kernel-netlink socket-default fips-prf eap-radius eap-identity updown
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+
+  plugins {
+    eap-radius {
+      secret = gv6URkSs
+      server = PH_IP_ALICE
+    }
+  }
+}
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..396eff5
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,30 @@
+connections {
+
+   rw {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey
+         certs = moonCert.pem
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = *@strongswan.org
+      }
+      remote-eap {
+         auth = eap-radius
+         eap_id = %any
+      }
+      children {
+         net {
+            local_ts  = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/posttest.dat b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/posttest.dat
new file mode 100644
index 0000000..25354d3
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/posttest.dat
@@ -0,0 +1,4 @@
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
+alice::killall radiusd
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/pretest.dat b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/pretest.dat
new file mode 100644
index 0000000..a6909c8
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/pretest.dat
@@ -0,0 +1,15 @@
+alice::cat /etc/freeradius/clients.conf
+alice::cat /etc/freeradius/eap.conf
+alice::cat /etc/freeradius/proxy.conf
+alice::cat /etc/freeradius/triplets.dat
+carol::cat /etc/ipsec.d/triplets.dat
+dave::cat /etc/ipsec.d/triplets.dat
+alice::radiusd
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
+carol::expect-connection home
+carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/test.conf b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/test.conf
new file mode 100644
index 0000000..6781150
--- /dev/null
+++ b/testing/tests/swanctl/mult-auth-rsa-eap-sim-id/test.conf
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# guest instances used for this test
+
+# All guest instances that are required for this test
+#
+VIRTHOSTS="alice moon carol winnetou dave"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-m-c-w-d.png"
+
+# Guest instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="moon"
+
+# Guest instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon carol dave"
+
+# Guest instances on which FreeRadius is started
+#
+RADIUSHOSTS="alice"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
+
diff --git a/testing/tests/swanctl/multi-level-ca/evaltest.dat b/testing/tests/swanctl/multi-level-ca/evaltest.dat
index 619f44b..050a35d 100644
--- a/testing/tests/swanctl/multi-level-ca/evaltest.dat
+++ b/testing/tests/swanctl/multi-level-ca/evaltest.dat
@@ -4,16 +4,16 @@ moon:: cat /var/log/daemon.log::fetching crl from.*http.*sales.crl::YES
 moon:: cat /var/log/daemon.log::crl correctly signed by.*Sales CA::YES
 moon:: cat /var/log/daemon.log::fetching crl from.*http.*strongswan.crl::YES
 moon:: cat /var/log/daemon.log::crl correctly signed by.*strongSwan Root CA::YES
-carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*alice.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.10/32]::YES
-moon:: swanctl --list-sas --raw 2> /dev/null::research.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*alice.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.10/32] remote-ts=\[192.168.0.100/32]::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*alice.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.100/32] remote-ts=\ [...]
+moon:: swanctl --list-sas --raw 2> /dev/null::research.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*alice.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.10/32] remote-ts=\ [...]
 carol::cat /var/log/daemon.log::received TS_UNACCEPTABLE notify, no CHILD_SA built::YES
 carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED.*child-sas.*venus.*state=INSTALLED::NO
-moon:: swanctl --list-sas --raw 2> /dev/null::sales.*version=2 state=ESTABLISHED.*remote-host=192.168.0.100 remote-id=carol at strongswan.org.*child-sas.*venus.*state=INSTALLED::NO
+moon:: swanctl --list-sas --raw 2> /dev/null::sales.*version=2 state=ESTABLISHED.*remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*child-sas.*venus.*state=INSTALLED::NO
 dave:: cat /var/log/daemon.log::received TS_UNACCEPTABLE notify, no CHILD_SA built::YES
 moon:: cat /var/log/daemon.log::constraint check failed: peer not authenticated by.*Research CA::YES
 moon:: cat /var/log/daemon.log::selected peer config.*research.*inacceptable::YES
 moon:: cat /var/log/daemon.log::switching to peer config.*sales::YES
 dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED.*child-sas.*alice.*state=INSTALLED::NO
-moon:: swanctl --list-sas --raw 2> /dev/null::research.*version=2 state=ESTABLISHED.*remote-host=192.168.0.100 remote-id=dave at strongswan.org.*child-sas.*alice.*state=INSTALLED::NO
-dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*venus.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.20/32]::YES
-moon:: swanctl --list-sas --raw 2> /dev/null::sales.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*venus.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.20/32] remote-ts=\[192.168.0.200/32]::YES
+moon:: swanctl --list-sas --raw 2> /dev/null::research.*version=2 state=ESTABLISHED.*remote-host=192.168.0.100 remote-port=4500 remote-id=dave at strongswan.org.*child-sas.*alice.*state=INSTALLED::NO
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*venus.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.200/32] remote-ts=\[ [...]
+moon:: swanctl --list-sas --raw 2> /dev/null::sales.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*venus.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.20/32] remote-ts=\[192 [...]
diff --git a/testing/tests/swanctl/multi-level-ca/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/multi-level-ca/hosts/carol/etc/swanctl/swanctl.conf
index 89fccff..e6c90c0 100755
--- a/testing/tests/swanctl/multi-level-ca/hosts/carol/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/multi-level-ca/hosts/carol/etc/swanctl/swanctl.conf
@@ -24,7 +24,6 @@ connections {
             esp_proposals = aes128-sha256-ecp256
          }
       }
-
       version = 2
       proposals = aes128-sha256-ecp256
    }
diff --git a/testing/tests/swanctl/multi-level-ca/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/multi-level-ca/hosts/dave/etc/swanctl/swanctl.conf
index 0a87ed3..5ca7bb5 100755
--- a/testing/tests/swanctl/multi-level-ca/hosts/dave/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/multi-level-ca/hosts/dave/etc/swanctl/swanctl.conf
@@ -24,7 +24,6 @@ connections {
             esp_proposals = aes128-sha256-ecp256
          }
       }
-
       version = 2
       proposals = aes128-sha256-ecp256
    }
diff --git a/testing/tests/swanctl/multi-level-ca/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/multi-level-ca/hosts/moon/etc/swanctl/swanctl.conf
index 496c5fd..574887d 100755
--- a/testing/tests/swanctl/multi-level-ca/hosts/moon/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/multi-level-ca/hosts/moon/etc/swanctl/swanctl.conf
@@ -19,7 +19,6 @@ connections {
             esp_proposals = aes128-sha256-ecp256
          }
       }
-
       version = 2
       proposals = aes128-sha256-ecp256
    }
@@ -43,7 +42,6 @@ connections {
             esp_proposals = aes128-sha256-ecp256
          }
       }
-
       version = 2
       proposals = aes128-sha256-ecp256
    }
diff --git a/testing/tests/swanctl/multi-level-ca/pretest.dat b/testing/tests/swanctl/multi-level-ca/pretest.dat
index 61ac75d..4c1be2e 100644
--- a/testing/tests/swanctl/multi-level-ca/pretest.dat
+++ b/testing/tests/swanctl/multi-level-ca/pretest.dat
@@ -1,8 +1,10 @@
 moon::service charon start 2> /dev/null
 carol::service charon start 2> /dev/null
 dave::service charon start 2> /dev/null
-moon::sleep 1
+moon::expect-connection research
+carol::expect-connection alice
 carol::swanctl --initiate --child alice 2> /dev/null
 carol::swanctl --initiate --child venus 2> /dev/null
+dave::expect-connection alice
 dave::swanctl --initiate --child alice 2> /dev/null
 dave::swanctl --initiate --child venus 2> /dev/null
diff --git a/testing/tests/swanctl/net2net-cert/evaltest.dat b/testing/tests/swanctl/net2net-cert/evaltest.dat
index cdbecd5..48a8857 100755
--- a/testing/tests/swanctl/net2net-cert/evaltest.dat
+++ b/testing/tests/swanctl/net2net-cert/evaltest.dat
@@ -1,5 +1,5 @@
-moon::swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.2.0.0/16]::YES
-sun:: swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.2.0.0/16] remote-ts=\[10.1.0.0/16]::YES
+moon::swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-port=500 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.2.0.0/16]::YES
+sun:: swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=500 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-port=500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.2.0.0/16] remote-ts=\[10.1.0.0/16]::YES
 alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
 sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
 sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/swanctl/net2net-cert/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/net2net-cert/hosts/moon/etc/swanctl/swanctl.conf
index 2f0fd9d..b1c005b 100755
--- a/testing/tests/swanctl/net2net-cert/hosts/moon/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/net2net-cert/hosts/moon/etc/swanctl/swanctl.conf
@@ -18,17 +18,12 @@ connections {
             local_ts  = 10.1.0.0/16 
             remote_ts = 10.2.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
       mobike = no
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
diff --git a/testing/tests/swanctl/net2net-cert/hosts/sun/etc/swanctl/swanctl.conf b/testing/tests/swanctl/net2net-cert/hosts/sun/etc/swanctl/swanctl.conf
index e4c8556..c351213 100755
--- a/testing/tests/swanctl/net2net-cert/hosts/sun/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/net2net-cert/hosts/sun/etc/swanctl/swanctl.conf
@@ -18,17 +18,12 @@ connections {
             local_ts  = 10.2.0.0/16 
             remote_ts = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
       mobike = no
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
diff --git a/testing/tests/swanctl/net2net-cert/pretest.dat b/testing/tests/swanctl/net2net-cert/pretest.dat
index 81410ff..b128bef 100755
--- a/testing/tests/swanctl/net2net-cert/pretest.dat
+++ b/testing/tests/swanctl/net2net-cert/pretest.dat
@@ -2,5 +2,6 @@ moon::iptables-restore < /etc/iptables.rules
 sun::iptables-restore < /etc/iptables.rules
 moon::service charon start 2> /dev/null
 sun::service charon start 2> /dev/null
-moon::sleep 1
+moon::expect-connection gw-gw
+sun::expect-connection gw-gw
 moon::swanctl --initiate --child net-net 2> /dev/null
diff --git a/testing/tests/swanctl/net2net-pubkey/description.txt b/testing/tests/swanctl/net2net-pubkey/description.txt
new file mode 100644
index 0000000..1cb90f1
--- /dev/null
+++ b/testing/tests/swanctl/net2net-pubkey/description.txt
@@ -0,0 +1,7 @@
+A connection between the subnets behind the gateways <b>moon</b> and <b>sun</b> is set up.
+The authentication is based on <b>raw RSA keys</b> loaded in PKCS#1 format.
+<p/>
+Upon the successful establishment of the IPsec tunnel, <b>leftfirewall=yes</b>
+automatically inserts iptables-based firewall rules that let pass the tunneled traffic.
+In order to test both tunnel and firewall, client <b>alice</b> behind gateway <b>moon</b>
+pings client <b>bob</b> located behind gateway <b>sun</b>.
diff --git a/testing/tests/swanctl/net2net-pubkey/evaltest.dat b/testing/tests/swanctl/net2net-pubkey/evaltest.dat
new file mode 100644
index 0000000..8491176
--- /dev/null
+++ b/testing/tests/swanctl/net2net-pubkey/evaltest.dat
@@ -0,0 +1,5 @@
+moon::swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-port=500 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.2.0.0/16]::YES
+sun:: swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=500 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-port=500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.2.0.0/16] remote-ts=\[10.1.0.0/16]::YES
+alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
+sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
+sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/swanctl/net2net-pubkey/hosts/moon/etc/strongswan.conf b/testing/tests/swanctl/net2net-pubkey/hosts/moon/etc/strongswan.conf
new file mode 100644
index 0000000..531e286
--- /dev/null
+++ b/testing/tests/swanctl/net2net-pubkey/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,10 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce openssl pem pkcs1 pubkey kernel-netlink socket-default vici updown
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/net2net-pubkey/hosts/moon/etc/swanctl/pubkey/moonPub.pem b/testing/tests/swanctl/net2net-pubkey/hosts/moon/etc/swanctl/pubkey/moonPub.pem
new file mode 100644
index 0000000..94fadce
--- /dev/null
+++ b/testing/tests/swanctl/net2net-pubkey/hosts/moon/etc/swanctl/pubkey/moonPub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApHwF+sUXQdH+WwYzdPMz
+pjuwhGGvHgsmBah1IQsPsddL9gZygerzpTM1vvQ4kbRuvE3SZWLf9uKEbiQV9IAB
+r87L9JAva56EHIAiUMuG8WizVbIKIhQlZc8S2mIwAW0Jc6EmnoJv9j6F/tVD9+6x
+vMJbwHLi0h7BUO9tBVLPy72YeGNBY6Cob4CrOuFOJyACezJ7i9vZ+XzOfnXpu7qL
+0DgYP/n2maPEJGEivTFunkJD/mJ8DecyLTQcchsCj2118BMuf2qjVn4UWPCBBuhy
+YK5wsATB1ANeAtlFfgH+wsuHjZwtTJru05lGHBZ3F2hZ9PO68hVHbIZZj6SB8X47
+nwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/net2net-pubkey/hosts/moon/etc/swanctl/pubkey/sunPub.pem b/testing/tests/swanctl/net2net-pubkey/hosts/moon/etc/swanctl/pubkey/sunPub.pem
new file mode 100644
index 0000000..5254ed1
--- /dev/null
+++ b/testing/tests/swanctl/net2net-pubkey/hosts/moon/etc/swanctl/pubkey/sunPub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxyIgBH1KWzMMmEYS1Gr1
+4IUBg120vdsLuNwQuzu22qIHnWIBSB2L0lkLOBY0AYd3wi9ENXnb0MOJTFfE5YJ1
+gpSZCnS3m9HqgTmmYeZ3mVxSC4TJWu2oVKvosxSo5fAVvjVVQ089HtjIsx2BR/0q
+LQ9lZ2dUtUSn9kohjU5qpktOfJ9XuTQj9dBfa5bpQMJoLUBAGWPMR+sPaBRwb34U
+ulvmoOyIZTKGEsH6czUY0+dm8iUKmkP7S3fEQjzv56Dk3zrJcFy7ij87uu9Wk/Xs
+auHAq5jHREcMFJwEOj9ZE0Q6ufz9D2NBSWvLTr7QKFVhj5HfbyUcAGRqgf+sHrkl
+IQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/net2net-pubkey/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/net2net-pubkey/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..08bc938
--- /dev/null
+++ b/testing/tests/swanctl/net2net-pubkey/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,30 @@
+connections {
+
+   gw-gw {
+      local_addrs  = 192.168.0.1
+      remote_addrs = 192.168.0.2 
+
+      local {
+         auth = pubkey 
+         pubkeys = moonPub.pem
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = pubkey
+         pubkeys = sunPub.pem
+         id = sun.strongswan.org 
+      }
+      children {
+         net-net {
+            local_ts  = 10.1.0.0/16 
+            remote_ts = 10.2.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-ecp256
+         }
+      }
+      version = 2
+      mobike = no
+      proposals = aes128-sha256-ecp256
+   }
+}
diff --git a/testing/tests/swanctl/net2net-pubkey/hosts/sun/etc/strongswan.conf b/testing/tests/swanctl/net2net-pubkey/hosts/sun/etc/strongswan.conf
new file mode 100644
index 0000000..531e286
--- /dev/null
+++ b/testing/tests/swanctl/net2net-pubkey/hosts/sun/etc/strongswan.conf
@@ -0,0 +1,10 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce openssl pem pkcs1 pubkey kernel-netlink socket-default vici updown
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/net2net-pubkey/hosts/sun/etc/swanctl/pubkey/moonPub.pem b/testing/tests/swanctl/net2net-pubkey/hosts/sun/etc/swanctl/pubkey/moonPub.pem
new file mode 100644
index 0000000..94fadce
--- /dev/null
+++ b/testing/tests/swanctl/net2net-pubkey/hosts/sun/etc/swanctl/pubkey/moonPub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApHwF+sUXQdH+WwYzdPMz
+pjuwhGGvHgsmBah1IQsPsddL9gZygerzpTM1vvQ4kbRuvE3SZWLf9uKEbiQV9IAB
+r87L9JAva56EHIAiUMuG8WizVbIKIhQlZc8S2mIwAW0Jc6EmnoJv9j6F/tVD9+6x
+vMJbwHLi0h7BUO9tBVLPy72YeGNBY6Cob4CrOuFOJyACezJ7i9vZ+XzOfnXpu7qL
+0DgYP/n2maPEJGEivTFunkJD/mJ8DecyLTQcchsCj2118BMuf2qjVn4UWPCBBuhy
+YK5wsATB1ANeAtlFfgH+wsuHjZwtTJru05lGHBZ3F2hZ9PO68hVHbIZZj6SB8X47
+nwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/net2net-pubkey/hosts/sun/etc/swanctl/pubkey/sunPub.pem b/testing/tests/swanctl/net2net-pubkey/hosts/sun/etc/swanctl/pubkey/sunPub.pem
new file mode 100644
index 0000000..5254ed1
--- /dev/null
+++ b/testing/tests/swanctl/net2net-pubkey/hosts/sun/etc/swanctl/pubkey/sunPub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxyIgBH1KWzMMmEYS1Gr1
+4IUBg120vdsLuNwQuzu22qIHnWIBSB2L0lkLOBY0AYd3wi9ENXnb0MOJTFfE5YJ1
+gpSZCnS3m9HqgTmmYeZ3mVxSC4TJWu2oVKvosxSo5fAVvjVVQ089HtjIsx2BR/0q
+LQ9lZ2dUtUSn9kohjU5qpktOfJ9XuTQj9dBfa5bpQMJoLUBAGWPMR+sPaBRwb34U
+ulvmoOyIZTKGEsH6czUY0+dm8iUKmkP7S3fEQjzv56Dk3zrJcFy7ij87uu9Wk/Xs
+auHAq5jHREcMFJwEOj9ZE0Q6ufz9D2NBSWvLTr7QKFVhj5HfbyUcAGRqgf+sHrkl
+IQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/net2net-pubkey/hosts/sun/etc/swanctl/swanctl.conf b/testing/tests/swanctl/net2net-pubkey/hosts/sun/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..e614509
--- /dev/null
+++ b/testing/tests/swanctl/net2net-pubkey/hosts/sun/etc/swanctl/swanctl.conf
@@ -0,0 +1,30 @@
+connections {
+
+   gw-gw {
+      local_addrs  = 192.168.0.2
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = pubkey 
+         pubkeys = sunPub.pem
+         id = sun.strongswan.org
+      }
+      remote {
+         auth = pubkey
+         pubkeys = moonPub.pem
+         id = moon.strongswan.org 
+      }
+      children {
+         net-net {
+            local_ts  = 10.2.0.0/16 
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-ecp256
+         }
+      }
+      version = 2
+      mobike = no
+      proposals = aes128-sha256-ecp256
+   }
+}
diff --git a/testing/tests/swanctl/net2net-pubkey/posttest.dat b/testing/tests/swanctl/net2net-pubkey/posttest.dat
new file mode 100644
index 0000000..c2227a5
--- /dev/null
+++ b/testing/tests/swanctl/net2net-pubkey/posttest.dat
@@ -0,0 +1,7 @@
+moon::swanctl --terminate --ike gw-gw 2> /dev/null
+moon::service charon stop 2> /dev/null
+sun::service charon stop 2> /dev/null
+moon::iptables-restore < /etc/iptables.flush
+sun::iptables-restore < /etc/iptables.flush
+moon::rm /etc/swanctl/pubkey/*
+sun::rm /etc/swanctl/pubkey/*
diff --git a/testing/tests/swanctl/net2net-pubkey/pretest.dat b/testing/tests/swanctl/net2net-pubkey/pretest.dat
new file mode 100644
index 0000000..11e7d50
--- /dev/null
+++ b/testing/tests/swanctl/net2net-pubkey/pretest.dat
@@ -0,0 +1,8 @@
+sun::iptables-restore < /etc/iptables.rules
+moon::iptables-restore < /etc/iptables.rules
+sun::cd /etc/swanctl; rm x509/* x509ca/*
+moon::cd /etc/swanctl; rm x509/* x509ca/*
+sun::service charon start 2> /dev/null
+moon::service charon start 2> /dev/null
+moon::expect-connection gw-gw
+moon::swanctl --initiate --child net-net 2> /dev/null
diff --git a/testing/tests/swanctl/net2net-pubkey/test.conf b/testing/tests/swanctl/net2net-pubkey/test.conf
new file mode 100644
index 0000000..07a3b24
--- /dev/null
+++ b/testing/tests/swanctl/net2net-pubkey/test.conf
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# guest instances used for this test
+
+# All guest instances that are required for this test
+#
+VIRTHOSTS="alice moon winnetou sun bob"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-m-w-s-b.png"
+ 
+# Guest instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="sun"
+
+# Guest instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon sun"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/swanctl/net2net-route/evaltest.dat b/testing/tests/swanctl/net2net-route/evaltest.dat
index 04df90b..ae292c1 100755
--- a/testing/tests/swanctl/net2net-route/evaltest.dat
+++ b/testing/tests/swanctl/net2net-route/evaltest.dat
@@ -1,7 +1,7 @@
 moon::swanctl --list-pols --raw 2> /dev/null::net-net.*mode=TUNNEL local-ts=\[10.1.0.0/16] remote-ts=\[10.2.0.0/16]::YES
 moon::cat /var/log/daemon.log::creating acquire job for policy 10.1.0.10/32\[icmp/8] === 10.2.0.10/32\[icmp/8]::YES
-moon::swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.2.0.0/16]::YES
-sun:: swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.2.0.0/16] remote-ts=\[10.1.0.0/16]::YES
+moon::swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-port=500 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.2.0.0/16]::YES
+sun:: swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=500 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-port=500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.2.0.0/16] remote-ts=\[10.1.0.0/16]::YES
 alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
 sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
 sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/swanctl/net2net-route/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/net2net-route/hosts/moon/etc/swanctl/swanctl.conf
index 1dfcfd1..3de6edc 100755
--- a/testing/tests/swanctl/net2net-route/hosts/moon/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/net2net-route/hosts/moon/etc/swanctl/swanctl.conf
@@ -20,15 +20,11 @@ connections {
 
             start_action = trap 
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
       mobike = no
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
diff --git a/testing/tests/swanctl/net2net-route/hosts/sun/etc/swanctl/swanctl.conf b/testing/tests/swanctl/net2net-route/hosts/sun/etc/swanctl/swanctl.conf
index e4c8556..5a9cd13 100755
--- a/testing/tests/swanctl/net2net-route/hosts/sun/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/net2net-route/hosts/sun/etc/swanctl/swanctl.conf
@@ -20,15 +20,11 @@ connections {
 
             start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
       mobike = no
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
diff --git a/testing/tests/swanctl/net2net-route/pretest.dat b/testing/tests/swanctl/net2net-route/pretest.dat
index 065d38d..459879b 100755
--- a/testing/tests/swanctl/net2net-route/pretest.dat
+++ b/testing/tests/swanctl/net2net-route/pretest.dat
@@ -2,5 +2,6 @@ sun::iptables-restore < /etc/iptables.rules
 moon::iptables-restore < /etc/iptables.rules
 sun::service charon start 2> /dev/null
 moon::service charon start 2> /dev/null
-moon::sleep 1
-alice::ping -c 3 10.2.0.10
+sun::expect-connection gw-gw
+moon::expect-connection gw-gw
+alice::ping -c 3 -W 1 -i 0.2 PH_IP_BOB
diff --git a/testing/tests/swanctl/net2net-start/evaltest.dat b/testing/tests/swanctl/net2net-start/evaltest.dat
index cdbecd5..48a8857 100755
--- a/testing/tests/swanctl/net2net-start/evaltest.dat
+++ b/testing/tests/swanctl/net2net-start/evaltest.dat
@@ -1,5 +1,5 @@
-moon::swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.2.0.0/16]::YES
-sun:: swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.2.0.0/16] remote-ts=\[10.1.0.0/16]::YES
+moon::swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-port=500 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[10.2.0.0/16]::YES
+sun:: swanctl --list-sas --raw 2> /dev/null::gw-gw.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=500 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-port=500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net-net.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.2.0.0/16] remote-ts=\[10.1.0.0/16]::YES
 alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
 sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
 sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/swanctl/net2net-start/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/net2net-start/hosts/moon/etc/swanctl/swanctl.conf
index 6770f6a..0713e7d 100755
--- a/testing/tests/swanctl/net2net-start/hosts/moon/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/net2net-start/hosts/moon/etc/swanctl/swanctl.conf
@@ -20,15 +20,11 @@ connections {
 
             start_action = start 
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
       mobike = no
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
diff --git a/testing/tests/swanctl/net2net-start/hosts/sun/etc/swanctl/swanctl.conf b/testing/tests/swanctl/net2net-start/hosts/sun/etc/swanctl/swanctl.conf
index e4c8556..5a9cd13 100755
--- a/testing/tests/swanctl/net2net-start/hosts/sun/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/net2net-start/hosts/sun/etc/swanctl/swanctl.conf
@@ -20,15 +20,11 @@ connections {
 
             start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
       mobike = no
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
diff --git a/testing/tests/swanctl/net2net-start/pretest.dat b/testing/tests/swanctl/net2net-start/pretest.dat
index e419836..6c1783b 100755
--- a/testing/tests/swanctl/net2net-start/pretest.dat
+++ b/testing/tests/swanctl/net2net-start/pretest.dat
@@ -2,4 +2,4 @@ sun::iptables-restore < /etc/iptables.rules
 moon::iptables-restore < /etc/iptables.rules
 sun::service charon start 2> /dev/null
 moon::service charon start 2> /dev/null
-moon::sleep 1
+moon::sleep 0.5
diff --git a/testing/tests/swanctl/ocsp-multi-level/evaltest.dat b/testing/tests/swanctl/ocsp-multi-level/evaltest.dat
index 48776c4..2f3c346 100644
--- a/testing/tests/swanctl/ocsp-multi-level/evaltest.dat
+++ b/testing/tests/swanctl/ocsp-multi-level/evaltest.dat
@@ -1,8 +1,8 @@
-moon:: swanctl --list-certs --type X509_OCSP_RESPONSE 2> /dev/null::subject.*ocsp.research.strongswan.org::YES
-moon:: swanctl --list-certs --type X509_OCSP_RESPONSE 2> /dev/null::subject.*ocsp.sales.strongswan.org::YES
-moon:: swanctl --list-certs --type X509_OCSP_RESPONSE 2> /dev/null::subject.*ocsp.strongswan.org::YES
-carol::swanctl --list-certs --type X509_OCSP_RESPONSE 2> /dev/null::subject.*ocsp.strongswan.org::YES
-dave:: swanctl --list-certs --type X509_OCSP_RESPONSE 2> /dev/null::subject.*ocsp.strongswan.org::YES
+moon:: swanctl --list-certs --type ocsp_response 2> /dev/null::issuer.*ocsp.research.strongswan.org::YES
+moon:: swanctl --list-certs --type ocsp_response 2> /dev/null::issuer.*ocsp.sales.strongswan.org::YES
+moon:: swanctl --list-certs --type ocsp_response 2> /dev/null::issuer.*ocsp.strongswan.org::YES
+carol::swanctl --list-certs --type ocsp_response 2> /dev/null::issuer.*ocsp.strongswan.org::YES
+dave:: swanctl --list-certs --type ocsp_response 2> /dev/null::issuer.*ocsp.strongswan.org::YES
 moon:: cat /var/log/daemon.log::ocsp response correctly signed by.*ocsp.research.strongswan.org::YES
 moon:: cat /var/log/daemon.log::ocsp response correctly signed by.*ocsp.sales.strongswan.org::YES
 moon:: cat /var/log/daemon.log::ocsp response correctly signed by.*ocsp.strongswan.org::YES
@@ -11,16 +11,16 @@ dave:: cat /var/log/daemon.log::ocsp response correctly signed by.*ocsp.strongsw
 moon:: cat /var/log/daemon.log::certificate status is good::YES
 carol::cat /var/log/daemon.log::certificate status is good::YES
 dave:: cat /var/log/daemon.log::certificate status is good::YES
-carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*alice.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.10/32]::YES
-moon:: swanctl --list-sas --raw 2> /dev/null::research.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*alice.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.10/32] remote-ts=\[192.168.0.100/32]::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*alice.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.100/32] remote-ts=\ [...]
+moon:: swanctl --list-sas --raw 2> /dev/null::research.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*alice.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.10/32] remote-ts=\ [...]
 carol::cat /var/log/daemon.log::received TS_UNACCEPTABLE notify, no CHILD_SA built::YES
 carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED.*child-sas.*venus.*state=INSTALLED::NO
-moon:: swanctl --list-sas --raw 2> /dev/null::sales.*version=2 state=ESTABLISHED.*remote-host=192.168.0.100 remote-id=carol at strongswan.org.*child-sas.*venus.*state=INSTALLED::NO
+moon:: swanctl --list-sas --raw 2> /dev/null::sales.*version=2 state=ESTABLISHED.*remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*child-sas.*venus.*state=INSTALLED::NO
 dave:: cat /var/log/daemon.log::received TS_UNACCEPTABLE notify, no CHILD_SA built::YES
 moon:: cat /var/log/daemon.log::constraint check failed: peer not authenticated by.*Research CA::YES
 moon:: cat /var/log/daemon.log::selected peer config.*research.*inacceptable::YES
 moon:: cat /var/log/daemon.log::switching to peer config.*sales::YES
 dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED.*child-sas.*alice.*state=INSTALLED::NO
-moon:: swanctl --list-sas --raw 2> /dev/null::research.*version=2 state=ESTABLISHED.*remote-host=192.168.0.100 remote-id=dave at strongswan.org.*child-sas.*alice.*state=INSTALLED::NO
-dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*venus.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.20/32]::YES
-moon:: swanctl --list-sas --raw 2> /dev/null::sales.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*venus.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.20/32] remote-ts=\[192.168.0.200/32]::YES
+moon:: swanctl --list-sas --raw 2> /dev/null::research.*version=2 state=ESTABLISHED.*remote-host=192.168.0.100 remote-port=4500 remote-id=dave at strongswan.org.*child-sas.*alice.*state=INSTALLED::NO
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*venus.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[192.168.0.200/32] remote-ts=\[ [...]
+moon:: swanctl --list-sas --raw 2> /dev/null::sales.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*venus.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts=\[10.1.0.20/32] remote-ts=\[192 [...]
diff --git a/testing/tests/swanctl/ocsp-multi-level/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/ocsp-multi-level/hosts/carol/etc/swanctl/swanctl.conf
index 26c3a89..7867fde 100755
--- a/testing/tests/swanctl/ocsp-multi-level/hosts/carol/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/ocsp-multi-level/hosts/carol/etc/swanctl/swanctl.conf
@@ -24,7 +24,6 @@ connections {
             esp_proposals = aes128-sha256-ecp256
          }
       }
-
       version = 2
       proposals = aes128-sha256-ecp256
    }
diff --git a/testing/tests/swanctl/ocsp-multi-level/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/ocsp-multi-level/hosts/dave/etc/swanctl/swanctl.conf
index 8752e9b..0c30521 100755
--- a/testing/tests/swanctl/ocsp-multi-level/hosts/dave/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/ocsp-multi-level/hosts/dave/etc/swanctl/swanctl.conf
@@ -24,7 +24,6 @@ connections {
             esp_proposals = aes128-sha256-ecp256
          }
       }
-
       version = 2
       proposals = aes128-sha256-ecp256
    }
diff --git a/testing/tests/swanctl/ocsp-multi-level/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/ocsp-multi-level/hosts/moon/etc/swanctl/swanctl.conf
index 2cb0501..c5beb2c 100755
--- a/testing/tests/swanctl/ocsp-multi-level/hosts/moon/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/ocsp-multi-level/hosts/moon/etc/swanctl/swanctl.conf
@@ -19,7 +19,6 @@ connections {
             esp_proposals = aes128-sha256-ecp256
          }
       }
-
       version = 2
       proposals = aes128-sha256-ecp256
    }
@@ -43,7 +42,6 @@ connections {
             esp_proposals = aes128-sha256-ecp256
          }
       }
-
       version = 2
       proposals = aes128-sha256-ecp256
    }
diff --git a/testing/tests/swanctl/ocsp-multi-level/pretest.dat b/testing/tests/swanctl/ocsp-multi-level/pretest.dat
index 61ac75d..7b83e21 100644
--- a/testing/tests/swanctl/ocsp-multi-level/pretest.dat
+++ b/testing/tests/swanctl/ocsp-multi-level/pretest.dat
@@ -1,8 +1,10 @@
 moon::service charon start 2> /dev/null
 carol::service charon start 2> /dev/null
 dave::service charon start 2> /dev/null
-moon::sleep 1
+moon::expect-connection research
+carol::expect-connection home
 carol::swanctl --initiate --child alice 2> /dev/null
 carol::swanctl --initiate --child venus 2> /dev/null
+dave::expect-connection home
 dave::swanctl --initiate --child alice 2> /dev/null
 dave::swanctl --initiate --child venus 2> /dev/null
diff --git a/testing/tests/swanctl/protoport-dual/description.txt b/testing/tests/swanctl/protoport-dual/description.txt
new file mode 100644
index 0000000..35c5b39
--- /dev/null
+++ b/testing/tests/swanctl/protoport-dual/description.txt
@@ -0,0 +1,7 @@
+Using <b>[<protocol>/<port>]</b> selectors in the
+<b>local_ts</b> and <b>remote_ts</b> child parameters, two IPsec tunnels
+between the roadwarrior <b>carol</b> and the gateway <b>moon</b> are defined.
+The first CHILD_SA is restricted to ICMP packets and the second
+covers TCP-based SSH connections. The established tunnels are tested
+by <b>carol</b> by first pinging <b>alice</b> behind <b>moon</b> and
+then setting up an SSH session to the same client.
diff --git a/testing/tests/swanctl/protoport-dual/evaltest.dat b/testing/tests/swanctl/protoport-dual/evaltest.dat
new file mode 100644
index 0000000..a471d1d
--- /dev/null
+++ b/testing/tests/swanctl/protoport-dual/evaltest.dat
@@ -0,0 +1,7 @@
+carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::ping -c 1 PH_IP_MOON1::64 bytes from PH_IP_MOON1: icmp_req=1::YES
+carol::ssh -o ConnectTimeout=5 PH_IP_ALICE hostname::alice::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*icmp.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32\[icmp]] remote-ts=\[10 [...]
+moon::swanctl --list-sas --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*icmp.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16\[icmp]] remote-ts=\[192.168.0.100/32\[icmp]] [...]
+moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
+moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
diff --git a/testing/tests/swanctl/protoport-dual/hosts/carol/etc/strongswan.conf b/testing/tests/swanctl/protoport-dual/hosts/carol/etc/strongswan.conf
new file mode 100644
index 0000000..5cf4d0c
--- /dev/null
+++ b/testing/tests/swanctl/protoport-dual/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,10 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/protoport-dual/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/protoport-dual/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..c33f05c
--- /dev/null
+++ b/testing/tests/swanctl/protoport-dual/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = pubkey
+         certs = carolCert.pem
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         icmp {
+            local_ts  = dynamic[icmp]
+            remote_ts = 10.1.0.0/16[icmp]
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+         ssh {
+            local_ts  = dynamic[tcp]
+            remote_ts = 10.1.0.0/16[tcp/ssh]
+            
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/swanctl/protoport-dual/hosts/moon/etc/strongswan.conf b/testing/tests/swanctl/protoport-dual/hosts/moon/etc/strongswan.conf
new file mode 100644
index 0000000..1065d9a
--- /dev/null
+++ b/testing/tests/swanctl/protoport-dual/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,10 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp random nonce x509 curl revocation hmac vici kernel-netlink socket-default updown
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/protoport-dual/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/protoport-dual/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..71d7099
--- /dev/null
+++ b/testing/tests/swanctl/protoport-dual/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   rw {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey
+         certs = moonCert.pem
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = pubkey
+      }
+      children {
+         icmp {
+            local_ts  = 10.1.0.0/16[icmp]
+            remote_ts = dynamic[icmp]
+
+            hostaccess = yes
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+         ssh {
+            local_ts  = 10.1.0.0/16[tcp/ssh]
+            remote_ts = dynamic[tcp]
+
+            hostaccess = yes
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/swanctl/protoport-dual/posttest.dat b/testing/tests/swanctl/protoport-dual/posttest.dat
new file mode 100644
index 0000000..2fc2bbb
--- /dev/null
+++ b/testing/tests/swanctl/protoport-dual/posttest.dat
@@ -0,0 +1,5 @@
+carol::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
+moon::iptables-restore < /etc/iptables.flush
+carol::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/swanctl/protoport-dual/pretest.dat b/testing/tests/swanctl/protoport-dual/pretest.dat
new file mode 100644
index 0000000..0e8e433
--- /dev/null
+++ b/testing/tests/swanctl/protoport-dual/pretest.dat
@@ -0,0 +1,8 @@
+moon::iptables-restore < /etc/iptables.rules
+carol::iptables-restore < /etc/iptables.rules
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+carol::expect-connection icmp
+carol::expect-connection ssh
+carol::swanctl --initiate --child icmp 2> /dev/null
+carol::swanctl --initiate --child ssh 2> /dev/null
diff --git a/testing/tests/swanctl/protoport-dual/test.conf b/testing/tests/swanctl/protoport-dual/test.conf
new file mode 100644
index 0000000..307c7e9
--- /dev/null
+++ b/testing/tests/swanctl/protoport-dual/test.conf
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# guest instances used for this test
+
+# All guest instances that are required for this test
+#
+VIRTHOSTS="alice moon carol winnetou"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-m-c-w.png"
+
+# Guest instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="moon"
+
+# Guest instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon carol"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/swanctl/protoport-range/description.txt b/testing/tests/swanctl/protoport-range/description.txt
new file mode 100644
index 0000000..b243822
--- /dev/null
+++ b/testing/tests/swanctl/protoport-range/description.txt
@@ -0,0 +1,7 @@
+Using <b>[<protocol>/<port>]</b> selectors in the
+<b>local_ts</b> and <b>remote_ts</b> child parameters, three IPsec tunnels
+between the roadwarrior <b>carol</b> and the gateway <b>moon</b> are defined.
+The first CHILD_SA is restricted to ICMP request packets, the second
+covers ICMP reply pachets and the third TCP-based FTP and SSH connections.
+The established tunnels are tested by <b>carol</b> by first pinging <b>alice</b>
+behind <b>moon</b> and then setting up an SSH session to the same client.
diff --git a/testing/tests/swanctl/protoport-range/evaltest.dat b/testing/tests/swanctl/protoport-range/evaltest.dat
new file mode 100644
index 0000000..89caa9b
--- /dev/null
+++ b/testing/tests/swanctl/protoport-range/evaltest.dat
@@ -0,0 +1,7 @@
+carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::ping -c 1 PH_IP_MOON1::64 bytes from PH_IP_MOON1: icmp_req=1::YES
+carol::ssh -o ConnectTimeout=5 PH_IP_ALICE hostname::alice::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*icmp-req.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32\[icmp/8]] remote-t [...]
+moon::swanctl --list-sas --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*icmp-req.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16\[icmp/8]] remote-ts=\[192.168.0.100/32\[ [...]
+moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
+moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
diff --git a/testing/tests/swanctl/protoport-range/hosts/carol/etc/strongswan.conf b/testing/tests/swanctl/protoport-range/hosts/carol/etc/strongswan.conf
new file mode 100644
index 0000000..5cf4d0c
--- /dev/null
+++ b/testing/tests/swanctl/protoport-range/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,10 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/protoport-range/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/protoport-range/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..4414172
--- /dev/null
+++ b/testing/tests/swanctl/protoport-range/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,42 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = pubkey
+         certs = carolCert.pem
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         icmp-req {
+            local_ts  = dynamic[icmp/2048]
+            remote_ts = 10.1.0.0/16[icmp/2048]
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+         icmp-rep {
+            local_ts  = dynamic[icmp/0]
+            remote_ts = 10.1.0.0/16[icmp/0]
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+         ftp-ssh {
+            local_ts  = dynamic[tcp/32768-65535]
+            remote_ts = 10.1.0.0/16[tcp/21-22]
+            
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/swanctl/protoport-range/hosts/moon/etc/strongswan.conf b/testing/tests/swanctl/protoport-range/hosts/moon/etc/strongswan.conf
new file mode 100644
index 0000000..1065d9a
--- /dev/null
+++ b/testing/tests/swanctl/protoport-range/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,10 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp random nonce x509 curl revocation hmac vici kernel-netlink socket-default updown
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/protoport-range/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/protoport-range/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..c5a2a71
--- /dev/null
+++ b/testing/tests/swanctl/protoport-range/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,43 @@
+connections {
+
+   rw {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey
+         certs = moonCert.pem
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = pubkey
+      }
+      children {
+         icmp-req {
+            local_ts  = 10.1.0.0/16[icmp/2048]
+            remote_ts = dynamic[icmp/2048]
+
+            hostaccess = yes
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+         icmp-rep {
+            local_ts  = 10.1.0.0/16[icmp/0]
+            remote_ts = dynamic[icmp/0]
+
+            hostaccess = yes
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+         ftp-ssh {
+            local_ts  = 10.1.0.0/16[tcp/21-22]
+            remote_ts = dynamic[tcp/32768-65535]
+
+            hostaccess = yes
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/swanctl/protoport-range/posttest.dat b/testing/tests/swanctl/protoport-range/posttest.dat
new file mode 100644
index 0000000..2fc2bbb
--- /dev/null
+++ b/testing/tests/swanctl/protoport-range/posttest.dat
@@ -0,0 +1,5 @@
+carol::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
+moon::iptables-restore < /etc/iptables.flush
+carol::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/swanctl/protoport-range/pretest.dat b/testing/tests/swanctl/protoport-range/pretest.dat
new file mode 100644
index 0000000..7e864f5
--- /dev/null
+++ b/testing/tests/swanctl/protoport-range/pretest.dat
@@ -0,0 +1,10 @@
+moon::iptables-restore < /etc/iptables.rules
+carol::iptables-restore < /etc/iptables.rules
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+carol::expect-connection icmp-req
+carol::expect-connection icmp-rep
+carol::expect-connection ftp-ssh
+carol::swanctl --initiate --child icmp-req 2> /dev/null
+carol::swanctl --initiate --child icmp-rep 2> /dev/null
+carol::swanctl --initiate --child ftp-ssh 2> /dev/null
diff --git a/testing/tests/swanctl/protoport-range/test.conf b/testing/tests/swanctl/protoport-range/test.conf
new file mode 100644
index 0000000..307c7e9
--- /dev/null
+++ b/testing/tests/swanctl/protoport-range/test.conf
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# guest instances used for this test
+
+# All guest instances that are required for this test
+#
+VIRTHOSTS="alice moon carol winnetou"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-m-c-w.png"
+
+# Guest instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="moon"
+
+# Guest instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon carol"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/swanctl/rw-cert/evaltest.dat b/testing/tests/swanctl/rw-cert/evaltest.dat
index ee3fb76..09bc82b 100755
--- a/testing/tests/swanctl/rw-cert/evaltest.dat
+++ b/testing/tests/swanctl/rw-cert/evaltest.dat
@@ -1,7 +1,7 @@
-carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/16]::YES
-dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.0/16]::YES
-moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]::YES
-moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/16]::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.0/16]::YES
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]::YES
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]::YES
 alice::ping -c 1 192.168.0.100::64 bytes from 192.168.0.100: icmp_req=1::YES
 alice::ping -c 1 192.168.0.200::64 bytes from 192.168.0.200: icmp_req=1::YES
 moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
diff --git a/testing/tests/swanctl/rw-cert/hosts/carol/etc/swanctl/rsa/carolKey.pem b/testing/tests/swanctl/rw-cert/hosts/carol/etc/swanctl/rsa/carolKey.pem
new file mode 100644
index 0000000..1454ec5
--- /dev/null
+++ b/testing/tests/swanctl/rw-cert/hosts/carol/etc/swanctl/rsa/carolKey.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,7E1D40A7901772BA4D22AF58AA2DC76F
+
+1jt4EsxtHvgpSLN8PA/kSVKgoAsBEBQb8RK6VGnZywMCnpJdLKdPisGGYKNPg53b
+/0AFBmQVE60M8icbSAIUrAtyKxaBkoc9A7ibNCjobi0UzXTm3GcZZ1EC4/lE9PQZ
+/2FbcPgQWN3kZraZDkeP9XBXl6PorES8xvQUxJ9pd4hL7/c28fIApGhEimkIZO8o
+Qb7bR2cNCLYQAR6PeDoqhV39gvWoh77wp1WB3tQVbkS6MI/xl3wY2QVdq3Sbszh+
+f6lDU/SZS8BU0f44FRoInPp0GasgJ7MCiuEIshjuNPa50QkMcnNJsSgVEuw2hjN6
+LvAXx7vPt9pKpQfnu7YSJUsXDYN6PyXt7sZ8hDqraYIcI6eMpEBaTpItPSV2eckv
+06KC24Oa66E1yufNFAY49S2OY+pJA0W5zmcCqCjdrfJ+wNQYKZpbrfGz4VRzlFJC
+e3VkmAFwA5rcZdlp/mU2XREy+TaWsHMnpL0NcMHGmsfkTgaJIkRWalrdxlNTeitr
+3boNHWk0ESyMcBYRpM3eNXsGpiYy93u0bhrPbnqJsV6miKqpbs1aBNjlJ9s1Y2fC
+sko5/v7uMjb5tLF3lWQZfTu+bYtpGxFrqHJjhd8yd4gL1cFi30JcjczhwRY3Dily
+c0BFekMGmPc1djn6tfIFu13X9xTxyidCpVaT9UGnOaQs9OF1u8XAnZDaQgPwjLiy
+UlOE8xQ60LrhWLD582FsFnZz56bZ+QOQRWDMsB8nJeqnFXKfcRlnr0qlG6lTfA8h
+XkK/qGpdVvivS+CpbhVP6ixdEfa91Rx4NjLj53LGqOYwFEkM/OAIuMJetBfx3v9T
+iQfv594KE32nv9besnKlmJr2cGQWBYg1pUOtFj/aZ00yuXacv8qwzbrt4xGGDYGO
+Aj5Yf93UEcVkTySO1xJ1yiC6GJv1lLm0i5StwykHypxFijKe/zOpgtHVa5v5igjO
+v6cfhfJGGgIPTYrtt+EDKXcayvy2e2U/3HYVCHYiiMPX8AvP/R6m7MGrzYxm/WyO
+t68EWXSDLfuR3qcIlpP4aSBxuSpKhY/dIkS/beKZ7Njx1s4jSuYDMbKuuCRFSU2H
+8ISHS0kh3FetiS8IyIYzxab+KQZwnVtiGj4oaAhgFTIIoH26Fv5+xka74JdzOSUA
+jR9puKuxaegVWQVBx4cCyg6hAdewRm64PAcbApZWrPvMPBfTZFnXeifmaurcdK8p
+p/1eLrrPnNM6+Fh6lcKdX74yHPz3eWP3K1njZegzWnChhEWElPhJr6qYNQjd+lAS
+7650RJ3CJLUxBffnRR9nTArxFNI5jGWg/plLJTaRT5x5qg1dGNMqntpoeiY++Ttk
+GFDGVIOICBze6SOvzkZBbuXLJSWmWj5g9J2cYsLoOvlwsDT7FzKl8p6VY4V+SQb+
+4PN8qZWmOeczaLEhZ1QLmTKFpz9+wUZsXeBd1s78bWJR0zhraMPa0UJ9GBGq6uQ0
+yZ4Xm5KHKcgoewCUQMekU9ECsmR5NuC7VFDaa1OdPEVnEYR1xtaWUY0lYKOiixnd
++85fSq/yAXI/r0O4ISA55o9y1kDqVibTwJacb6xXGg8dHSH+TtigwD8fK9mekkDC
+-----END RSA PRIVATE KEY-----
diff --git a/testing/tests/swanctl/rw-cert/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-cert/hosts/carol/etc/swanctl/swanctl.conf
index 0ba2433..6cdc7bd 100755
--- a/testing/tests/swanctl/rw-cert/hosts/carol/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/rw-cert/hosts/carol/etc/swanctl/swanctl.conf
@@ -17,16 +17,19 @@ connections {
          home {
             remote_ts = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   rsa-carol {
+      file = carolKey.pem
+      secret = "nH5ZQEWtku0RJEZ6"
    }
 }
diff --git a/testing/tests/swanctl/rw-cert/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-cert/hosts/dave/etc/swanctl/swanctl.conf
index a3420a4..e65ec7a 100755
--- a/testing/tests/swanctl/rw-cert/hosts/dave/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/rw-cert/hosts/dave/etc/swanctl/swanctl.conf
@@ -17,16 +17,11 @@ connections {
          home {
             remote_ts = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
diff --git a/testing/tests/swanctl/rw-cert/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-cert/hosts/moon/etc/swanctl/swanctl.conf
index 861d65a..a3c51c8 100755
--- a/testing/tests/swanctl/rw-cert/hosts/moon/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/rw-cert/hosts/moon/etc/swanctl/swanctl.conf
@@ -15,16 +15,11 @@ connections {
          net {
             local_ts  = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
diff --git a/testing/tests/swanctl/rw-cert/pretest.dat b/testing/tests/swanctl/rw-cert/pretest.dat
index 706bd1e..762c354 100755
--- a/testing/tests/swanctl/rw-cert/pretest.dat
+++ b/testing/tests/swanctl/rw-cert/pretest.dat
@@ -4,6 +4,8 @@ dave::iptables-restore < /etc/iptables.rules
 moon::service charon start 2> /dev/null
 carol::service charon start 2> /dev/null
 dave::service charon start 2> /dev/null
-moon::sleep 1
+moon::expect-connection rw
+carol::expect-connection home
 carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
 dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/rw-dnssec/description.txt b/testing/tests/swanctl/rw-dnssec/description.txt
new file mode 100644
index 0000000..0135f07
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/description.txt
@@ -0,0 +1,10 @@
+The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each to gateway <b>moon</b>.
+The authentication is based on trustworthy public keys stored as <b>IPSECKEY</b>
+resource records in the Domain Name System (DNS) and protected by <b>DNSSEC</b>.
+</p>
+Both <b>carol</b> and <b>dave</b> request a <b>virtual IP</b> via the IKEv2 configuration payload
+by using the <b>leftsourceip=%config</b> parameter. <b>leftfirewall=yes</b> automatically
+inserts iptables-based firewall rules that let pass the tunneled traffic. In order to test the
+tunnels, <b>carol</b> and <b>dave</b> then ping the client <b>alice</b> behind the gateway
+<b>moon</b>. The source IP addresses of the two pings will be the virtual IPs <b>carol1</b>
+and <b>dave1</b>, respectively.
diff --git a/testing/tests/swanctl/rw-dnssec/evaltest.dat b/testing/tests/swanctl/rw-dnssec/evaltest.dat
new file mode 100644
index 0000000..6792334
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/evaltest.dat
@@ -0,0 +1,20 @@
+carol::cat /var/log/daemon.log::performing a DNS query for IPSECKEY RRs of.*moon.strongswan.org::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol.strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.3.0.1] child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.3.0.1/32] rem [...]
+carol::cat /var/log/daemon.log::installing new virtual IP PH_IP_CAROL1::YES
+carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+dave:: cat /var/log/daemon.log::performing a DNS query for IPSECKEY RRs of.*moon.strongswan.org::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave.strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.3.0.2] child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.3.0.2/32] remo [...]
+dave:: cat /var/log/daemon.log::installing new virtual IP PH_IP_DAVE1::YES
+dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+moon:: cat /var/log/daemon.log::performing a DNS query for IPSECKEY RRs of.*carol.strongswan.org::YES
+moon:: cat /var/log/daemon.log::performing a DNS query for IPSECKEY RRs of.*dave.strongswan.org::YES
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.3.0.1] child-sas.*net.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-t [...]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.3.0.2] child-sas.*net.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts [...]
+moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
+moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
+moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
+moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES
+alice::tcpdump::IP carol1.strongswan.org > alice.strongswan.org: ICMP echo request::YES
+alice::tcpdump::IP alice.strongswan.org > carol1.strongswan.org: ICMP echo reply::YES
+alice::tcpdump::IP dave1.strongswan.org > alice.strongswan.org: ICMP echo request::YES
+alice::tcpdump::IP alice.strongswan.org > dave1.strongswan.org: ICMP echo reply::YES
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/iptables.rules b/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/iptables.rules
new file mode 100644
index 0000000..b2c4252
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/iptables.rules
@@ -0,0 +1,28 @@
+*filter
+
+# default policy is DROP
+-P INPUT DROP
+-P OUTPUT DROP
+-P FORWARD DROP
+
+# allow esp
+-A INPUT  -i eth0 -p 50 -j ACCEPT
+-A OUTPUT -o eth0 -p 50 -j ACCEPT
+
+# allow IKE
+-A INPUT  -i eth0 -p udp --sport 500 --dport 500 -j ACCEPT
+-A OUTPUT -o eth0 -p udp --dport 500 --sport 500 -j ACCEPT
+
+# allow MobIKE
+-A INPUT  -i eth0 -p udp --sport 4500 --dport 4500 -j ACCEPT
+-A OUTPUT -o eth0 -p udp --dport 4500 --sport 4500 -j ACCEPT
+
+# allow ssh
+-A INPUT  -p tcp --dport 22 -j ACCEPT
+-A OUTPUT -p tcp --sport 22 -j ACCEPT
+
+# allow DNSSEC fetch from winnetou
+-A INPUT  -i eth0 -p udp --sport 53 -s PH_IP_WINNETOU -j ACCEPT
+-A OUTPUT -o eth0 -p udp --dport 53 -d PH_IP_WINNETOU -j ACCEPT
+
+COMMIT
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/resolv.conf b/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/resolv.conf
new file mode 100644
index 0000000..73d926d
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/resolv.conf
@@ -0,0 +1 @@
+nameserver PH_IP_WINNETOU
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/strongswan.conf b/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/strongswan.conf
new file mode 100644
index 0000000..7913daf
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,19 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp dnskey pubkey unbound ipseckey hmac vici kernel-netlink socket-default updown resolve
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+
+  plugins {
+    ipseckey {
+      enable = yes
+    }
+    unbound {
+      trust_anchors = /etc/swanctl/dnssec.keys
+    }
+  }
+}
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/swanctl/dnssec.keys b/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/swanctl/dnssec.keys
new file mode 100644
index 0000000..d059d84
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/swanctl/dnssec.keys
@@ -0,0 +1,10 @@
+; This is a key-signing key, keyid 32329, for .
+.		IN	DNSKEY	257 3 8	(
+				AwEAAbcskaratFgvgvXl0bNq4I43ZBzd9jYnoPqsIcA0ahqXlUTUa+c2
+				XzN2mS7DGcI4Z5Gn+8v/Ih4lQJQrlf9I/c2HjooCAsK1bA5cRS2DiU+b
+				L6Ge0nLtvNOf4C0MHGLrWcDONg5QoL0OcFvMXuUtOvDkoIMdtfDYDScx
+				E9vSokc98Sx553/MTxpssXeM9i+OauGqohIZU+MVRdWwvJPieCL7Ma4b
+				AttgG+KSbQy7x/qXPISoqzwGQvCxsL93fvD/cpp+KziqA0oH+Dfryvc5
+				nWdCdra4gYz7WCFFwcY1PW6PbL5ie4jnjl3WWxopuzT46HKROxDhE+FO
+				O9fOgGnjzAk=
+				)
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/swanctl/pubkey/carolPub.der b/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/swanctl/pubkey/carolPub.der
new file mode 100644
index 0000000..0c1140d
Binary files /dev/null and b/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/swanctl/pubkey/carolPub.der differ
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..2d14b32
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,28 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+      vips = 0.0.0.0
+
+      local {
+         auth = pubkey
+         id = carol.strongswan.org
+         pubkeys = carolPub.der
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/iptables.rules b/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/iptables.rules
new file mode 100644
index 0000000..b2c4252
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/iptables.rules
@@ -0,0 +1,28 @@
+*filter
+
+# default policy is DROP
+-P INPUT DROP
+-P OUTPUT DROP
+-P FORWARD DROP
+
+# allow esp
+-A INPUT  -i eth0 -p 50 -j ACCEPT
+-A OUTPUT -o eth0 -p 50 -j ACCEPT
+
+# allow IKE
+-A INPUT  -i eth0 -p udp --sport 500 --dport 500 -j ACCEPT
+-A OUTPUT -o eth0 -p udp --dport 500 --sport 500 -j ACCEPT
+
+# allow MobIKE
+-A INPUT  -i eth0 -p udp --sport 4500 --dport 4500 -j ACCEPT
+-A OUTPUT -o eth0 -p udp --dport 4500 --sport 4500 -j ACCEPT
+
+# allow ssh
+-A INPUT  -p tcp --dport 22 -j ACCEPT
+-A OUTPUT -p tcp --sport 22 -j ACCEPT
+
+# allow DNSSEC fetch from winnetou
+-A INPUT  -i eth0 -p udp --sport 53 -s PH_IP_WINNETOU -j ACCEPT
+-A OUTPUT -o eth0 -p udp --dport 53 -d PH_IP_WINNETOU -j ACCEPT
+
+COMMIT
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/resolv.conf b/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/resolv.conf
new file mode 100644
index 0000000..73d926d
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/resolv.conf
@@ -0,0 +1 @@
+nameserver PH_IP_WINNETOU
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/strongswan.conf b/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/strongswan.conf
new file mode 100644
index 0000000..7913daf
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,19 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp dnskey pubkey unbound ipseckey hmac vici kernel-netlink socket-default updown resolve
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+
+  plugins {
+    ipseckey {
+      enable = yes
+    }
+    unbound {
+      trust_anchors = /etc/swanctl/dnssec.keys
+    }
+  }
+}
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/swanctl/dnssec.keys b/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/swanctl/dnssec.keys
new file mode 100644
index 0000000..d059d84
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/swanctl/dnssec.keys
@@ -0,0 +1,10 @@
+; This is a key-signing key, keyid 32329, for .
+.		IN	DNSKEY	257 3 8	(
+				AwEAAbcskaratFgvgvXl0bNq4I43ZBzd9jYnoPqsIcA0ahqXlUTUa+c2
+				XzN2mS7DGcI4Z5Gn+8v/Ih4lQJQrlf9I/c2HjooCAsK1bA5cRS2DiU+b
+				L6Ge0nLtvNOf4C0MHGLrWcDONg5QoL0OcFvMXuUtOvDkoIMdtfDYDScx
+				E9vSokc98Sx553/MTxpssXeM9i+OauGqohIZU+MVRdWwvJPieCL7Ma4b
+				AttgG+KSbQy7x/qXPISoqzwGQvCxsL93fvD/cpp+KziqA0oH+Dfryvc5
+				nWdCdra4gYz7WCFFwcY1PW6PbL5ie4jnjl3WWxopuzT46HKROxDhE+FO
+				O9fOgGnjzAk=
+				)
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/swanctl/pubkey/davePub.der b/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/swanctl/pubkey/davePub.der
new file mode 100644
index 0000000..fc36c65
Binary files /dev/null and b/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/swanctl/pubkey/davePub.der differ
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..ba511a4
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,28 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+      vips = 0.0.0.0
+
+      local {
+         auth = pubkey
+         id = dave.strongswan.org
+         pubkeys = davePub.der
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/iptables.rules b/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/iptables.rules
new file mode 100644
index 0000000..b2c4252
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/iptables.rules
@@ -0,0 +1,28 @@
+*filter
+
+# default policy is DROP
+-P INPUT DROP
+-P OUTPUT DROP
+-P FORWARD DROP
+
+# allow esp
+-A INPUT  -i eth0 -p 50 -j ACCEPT
+-A OUTPUT -o eth0 -p 50 -j ACCEPT
+
+# allow IKE
+-A INPUT  -i eth0 -p udp --sport 500 --dport 500 -j ACCEPT
+-A OUTPUT -o eth0 -p udp --dport 500 --sport 500 -j ACCEPT
+
+# allow MobIKE
+-A INPUT  -i eth0 -p udp --sport 4500 --dport 4500 -j ACCEPT
+-A OUTPUT -o eth0 -p udp --dport 4500 --sport 4500 -j ACCEPT
+
+# allow ssh
+-A INPUT  -p tcp --dport 22 -j ACCEPT
+-A OUTPUT -p tcp --sport 22 -j ACCEPT
+
+# allow DNSSEC fetch from winnetou
+-A INPUT  -i eth0 -p udp --sport 53 -s PH_IP_WINNETOU -j ACCEPT
+-A OUTPUT -o eth0 -p udp --dport 53 -d PH_IP_WINNETOU -j ACCEPT
+
+COMMIT
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/resolv.conf b/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/resolv.conf
new file mode 100644
index 0000000..73d926d
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/resolv.conf
@@ -0,0 +1 @@
+nameserver PH_IP_WINNETOU
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/strongswan.conf b/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/strongswan.conf
new file mode 100644
index 0000000..9eafa0d
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,22 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 dnskey pubkey unbound ipseckey gmp hmac vici kernel-netlink socket-default updown attr
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds
+    pools = /usr/local/sbin/swanctl --load-pools 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+  dns1 = PH_IP_WINNETOU
+  dns2 = PH_IP_VENUS
+
+  plugins {
+    ipseckey {
+      enable = yes
+    }
+    unbound {
+      trust_anchors = /etc/swanctl/dnssec.keys
+    }
+  }
+}
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/swanctl/dnssec.keys b/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/swanctl/dnssec.keys
new file mode 100644
index 0000000..d059d84
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/swanctl/dnssec.keys
@@ -0,0 +1,10 @@
+; This is a key-signing key, keyid 32329, for .
+.		IN	DNSKEY	257 3 8	(
+				AwEAAbcskaratFgvgvXl0bNq4I43ZBzd9jYnoPqsIcA0ahqXlUTUa+c2
+				XzN2mS7DGcI4Z5Gn+8v/Ih4lQJQrlf9I/c2HjooCAsK1bA5cRS2DiU+b
+				L6Ge0nLtvNOf4C0MHGLrWcDONg5QoL0OcFvMXuUtOvDkoIMdtfDYDScx
+				E9vSokc98Sx553/MTxpssXeM9i+OauGqohIZU+MVRdWwvJPieCL7Ma4b
+				AttgG+KSbQy7x/qXPISoqzwGQvCxsL93fvD/cpp+KziqA0oH+Dfryvc5
+				nWdCdra4gYz7WCFFwcY1PW6PbL5ie4jnjl3WWxopuzT46HKROxDhE+FO
+				O9fOgGnjzAk=
+				)
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/swanctl/pubkey/moonPub.der b/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/swanctl/pubkey/moonPub.der
new file mode 100644
index 0000000..6724735
Binary files /dev/null and b/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/swanctl/pubkey/moonPub.der differ
diff --git a/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..33c4170
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,32 @@
+connections {
+
+   rw {
+      local_addrs  = 192.168.0.1
+      pools = rw_pool
+
+      local {
+         auth = pubkey
+         id = moon.strongswan.org
+         pubkeys = moonPub.der
+      }
+      remote {
+         auth = pubkey
+      }
+      children {
+         net {
+            local_ts  = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+pools {
+   rw_pool {
+      addrs = 10.3.0.0/28
+   }
+}
diff --git a/testing/tests/swanctl/rw-dnssec/posttest.dat b/testing/tests/swanctl/rw-dnssec/posttest.dat
new file mode 100644
index 0000000..48a4abe
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/posttest.dat
@@ -0,0 +1,11 @@
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
+moon::rm /etc/swanctl/pubkey/*
+carol::rm /etc/swanctl/pubkey/*
+dave::rm /etc/swanctl/pubkey/*
+moon::iptables-restore < /etc/iptables.flush
+carol::iptables-restore < /etc/iptables.flush
+dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/swanctl/rw-dnssec/pretest.dat b/testing/tests/swanctl/rw-dnssec/pretest.dat
new file mode 100644
index 0000000..5faf602
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/pretest.dat
@@ -0,0 +1,14 @@
+moon::iptables-restore < /etc/iptables.rules
+carol::iptables-restore < /etc/iptables.rules
+dave::iptables-restore < /etc/iptables.rules
+moon::cd /etc/swanctl; rm x509/* x509ca/*
+carol::cd /etc/swanctl; rm x509/* x509ca/*
+dave::cd /etc/swanctl; rm x509/* x509ca/*
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
+carol::expect-connection home
+carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/rw-dnssec/test.conf b/testing/tests/swanctl/rw-dnssec/test.conf
new file mode 100644
index 0000000..a542d03
--- /dev/null
+++ b/testing/tests/swanctl/rw-dnssec/test.conf
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# guest instances used for this test
+
+# All guest instances that are required for this test
+#
+VIRTHOSTS="alice moon carol winnetou dave"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-m-c-w-d.png"
+
+# Guest instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="moon alice"
+
+# Guest instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon carol dave"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/swanctl/rw-hash-and-url/evaltest.dat b/testing/tests/swanctl/rw-hash-and-url/evaltest.dat
index 5242db1..5286ffe 100755
--- a/testing/tests/swanctl/rw-hash-and-url/evaltest.dat
+++ b/testing/tests/swanctl/rw-hash-and-url/evaltest.dat
@@ -2,10 +2,10 @@ carol::cat /var/log/daemon.log::fetched certificate.*moon.strongswan.org::YES
 dave:: cat /var/log/daemon.log::fetched certificate.*moon.strongswan.org::YES
 moon:: cat /var/log/daemon.log::fetched certificate.*carol at strongswan.org::YES
 moon:: cat /var/log/daemon.log::fetched certificate.*dave at strongswan.org::YES
-carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/16]::YES
-dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.0/16]::YES
-moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]::YES
-moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/16]::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.0/16]::YES
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]::YES
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]::YES
 alice::ping -c 1 192.168.0.100::64 bytes from 192.168.0.100: icmp_req=1::YES
 alice::ping -c 1 192.168.0.200::64 bytes from 192.168.0.200: icmp_req=1::YES
 moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
diff --git a/testing/tests/swanctl/rw-hash-and-url/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-hash-and-url/hosts/carol/etc/swanctl/swanctl.conf
index 7b0b2ad..401b9fa 100755
--- a/testing/tests/swanctl/rw-hash-and-url/hosts/carol/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/rw-hash-and-url/hosts/carol/etc/swanctl/swanctl.conf
@@ -17,17 +17,12 @@ connections {
          home {
             remote_ts = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
 
diff --git a/testing/tests/swanctl/rw-hash-and-url/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-hash-and-url/hosts/dave/etc/swanctl/swanctl.conf
index b4d8209..b1e734d 100755
--- a/testing/tests/swanctl/rw-hash-and-url/hosts/dave/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/rw-hash-and-url/hosts/dave/etc/swanctl/swanctl.conf
@@ -17,17 +17,12 @@ connections {
          home {
             remote_ts = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
 
diff --git a/testing/tests/swanctl/rw-hash-and-url/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-hash-and-url/hosts/moon/etc/swanctl/swanctl.conf
index 258d9e8..f893175 100755
--- a/testing/tests/swanctl/rw-hash-and-url/hosts/moon/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/rw-hash-and-url/hosts/moon/etc/swanctl/swanctl.conf
@@ -15,17 +15,12 @@ connections {
          net {
             local_ts  = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
 
diff --git a/testing/tests/swanctl/rw-hash-and-url/pretest.dat b/testing/tests/swanctl/rw-hash-and-url/pretest.dat
index 706bd1e..762c354 100755
--- a/testing/tests/swanctl/rw-hash-and-url/pretest.dat
+++ b/testing/tests/swanctl/rw-hash-and-url/pretest.dat
@@ -4,6 +4,8 @@ dave::iptables-restore < /etc/iptables.rules
 moon::service charon start 2> /dev/null
 carol::service charon start 2> /dev/null
 dave::service charon start 2> /dev/null
-moon::sleep 1
+moon::expect-connection rw
+carol::expect-connection home
 carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
 dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/rw-ntru-bliss/description.txt b/testing/tests/swanctl/rw-ntru-bliss/description.txt
new file mode 100644
index 0000000..82ebd89
--- /dev/null
+++ b/testing/tests/swanctl/rw-ntru-bliss/description.txt
@@ -0,0 +1,14 @@
+The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each to gateway <b>moon</b>.
+The key exchange is based on NTRU encryption with a cryptographical strength of 128 bit and
+192 bit for <b>carol</b> and <b>dave</b>, respectively. Authentication is based on the BLISS
+algorithm with strengths 128 bits (BLISS I), 160 bits (BLISS III) and 192 bits (BLISS IV) for
+<b>carol</b>, <b>dave</b> and <b>moon</b>, respectively.
+<p>
+Both <b>carol</b> and <b>dave</b> request a <b>virtual IP</b> via the IKEv2 configuration payload.
+The gateway <b>moon</b> assigns virtual IP addresses from the pool 10.3.0.0/28 in a monotonously
+increasing order. 
+<p>
+The updown script automatically inserts iptables-based firewall rules that let pass
+the tunneled traffic. In order to test the tunnels, <b>carol</b> and <b>dave</b> then ping
+the client <b>alice</b> behind the gateway <b>moon</b>. The source IP addresses of the two
+pings will be the virtual IPs <b>carol1</b> and <b>dave1</b>, respectively.
diff --git a/testing/tests/swanctl/rw-ntru-bliss/evaltest.dat b/testing/tests/swanctl/rw-ntru-bliss/evaltest.dat
new file mode 100644
index 0000000..69149cd
--- /dev/null
+++ b/testing/tests/swanctl/rw-ntru-bliss/evaltest.dat
@@ -0,0 +1,18 @@
+carol::cat /var/log/daemon.log::authentication of.*moon.strongswan.org.*with BLISS_WITH_SHA2_512 successful::YES
+carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+dave::cat /var/log/daemon.log::authentication of.*moon.strongswan.org.*with BLISS_WITH_SHA2_512 successful::YES
+dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+moon:: cat /var/log/daemon.log::authentication of.*carol at strongswan.org.*with BLISS_WITH_SHA2_256 successful::YES
+moon:: cat /var/log/daemon.log::authentication of.*dave at strongswan.org.*with BLISS_WITH_SHA2_384 successful::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=NTRU_128.*local-vips=\[10.3.0.1] child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*loc [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=192 integ-alg=HMAC_SHA2_384_192 prf-alg=PRF_HMAC_SHA2_384 dh-group=NTRU_192.*local-vips=\[10.3.0.2] child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=192 integ-alg=HMAC_SHA2_384_192.*loca [...]
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=NTRU_128.*remote-vips=\[10.3.0.1] child-sas.*net.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128.*local-ts [...]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=192 integ-alg=HMAC_SHA2_384_192 prf-alg=PRF_HMAC_SHA2_384 dh-group=NTRU_192.*remote-vips=\[10.3.0.2] child-sas.*net.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_CBC encr-keysize=192 integ-alg=HMAC_SHA2_384_192.*local-ts= [...]
+moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
+moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
+moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
+moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES
+alice::tcpdump::IP carol1.strongswan.org > alice.strongswan.org: ICMP echo request::YES
+alice::tcpdump::IP alice.strongswan.org > carol1.strongswan.org: ICMP echo reply::YES
+alice::tcpdump::IP dave1.strongswan.org > alice.strongswan.org: ICMP echo request::YES
+alice::tcpdump::IP alice.strongswan.org > dave1.strongswan.org: ICMP echo reply::YES
diff --git a/testing/tests/swanctl/rw-ntru-bliss/hosts/carol/etc/strongswan.conf b/testing/tests/swanctl/rw-ntru-bliss/hosts/carol/etc/strongswan.conf
new file mode 100644
index 0000000..1a8d362
--- /dev/null
+++ b/testing/tests/swanctl/rw-ntru-bliss/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce aes sha1 sha2 sha3 hmac ntru bliss x509 revocation pem pkcs1 curl vici kernel-netlink socket-default updown
+
+  send_vendor_id = yes
+  fragment_size = 1500
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/rw-ntru-bliss/hosts/carol/etc/swanctl/bliss/carolKey.der b/testing/tests/swanctl/rw-ntru-bliss/hosts/carol/etc/swanctl/bliss/carolKey.der
new file mode 100644
index 0000000..b2831a8
Binary files /dev/null and b/testing/tests/swanctl/rw-ntru-bliss/hosts/carol/etc/swanctl/bliss/carolKey.der differ
diff --git a/testing/tests/swanctl/rw-ntru-bliss/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-ntru-bliss/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..fbfe57d
--- /dev/null
+++ b/testing/tests/swanctl/rw-ntru-bliss/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,30 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+      vips = 0.0.0.0
+
+      local {
+         auth = pubkey
+         certs = carolCert.der
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org
+         revocation = strict 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128-sha256-ntru128
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-ntru128
+      fragmentation = yes
+   }
+}
diff --git a/testing/tests/swanctl/rw-ntru-bliss/hosts/carol/etc/swanctl/x509/carolCert.der b/testing/tests/swanctl/rw-ntru-bliss/hosts/carol/etc/swanctl/x509/carolCert.der
new file mode 100644
index 0000000..8a520c0
Binary files /dev/null and b/testing/tests/swanctl/rw-ntru-bliss/hosts/carol/etc/swanctl/x509/carolCert.der differ
diff --git a/testing/tests/swanctl/rw-ntru-bliss/hosts/carol/etc/swanctl/x509ca/strongswan_blissCert.der b/testing/tests/swanctl/rw-ntru-bliss/hosts/carol/etc/swanctl/x509ca/strongswan_blissCert.der
new file mode 100644
index 0000000..fdfd39f
Binary files /dev/null and b/testing/tests/swanctl/rw-ntru-bliss/hosts/carol/etc/swanctl/x509ca/strongswan_blissCert.der differ
diff --git a/testing/tests/swanctl/rw-ntru-bliss/hosts/dave/etc/strongswan.conf b/testing/tests/swanctl/rw-ntru-bliss/hosts/dave/etc/strongswan.conf
new file mode 100644
index 0000000..1a8d362
--- /dev/null
+++ b/testing/tests/swanctl/rw-ntru-bliss/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce aes sha1 sha2 sha3 hmac ntru bliss x509 revocation pem pkcs1 curl vici kernel-netlink socket-default updown
+
+  send_vendor_id = yes
+  fragment_size = 1500
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/rw-ntru-bliss/hosts/dave/etc/swanctl/bliss/daveKey.der b/testing/tests/swanctl/rw-ntru-bliss/hosts/dave/etc/swanctl/bliss/daveKey.der
new file mode 100644
index 0000000..0ec528d
Binary files /dev/null and b/testing/tests/swanctl/rw-ntru-bliss/hosts/dave/etc/swanctl/bliss/daveKey.der differ
diff --git a/testing/tests/swanctl/rw-ntru-bliss/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-ntru-bliss/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..ec04538
--- /dev/null
+++ b/testing/tests/swanctl/rw-ntru-bliss/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,30 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+      vips = 0.0.0.0
+
+      local {
+         auth = pubkey
+         certs = daveCert.der
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org
+         revocation = strict 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes192-sha384-ntru192
+         }
+      }
+      version = 2
+      proposals = aes192-sha384-ntru192
+      fragmentation = yes
+   }
+}
diff --git a/testing/tests/swanctl/rw-ntru-bliss/hosts/dave/etc/swanctl/x509/daveCert.der b/testing/tests/swanctl/rw-ntru-bliss/hosts/dave/etc/swanctl/x509/daveCert.der
new file mode 100644
index 0000000..75a1143
Binary files /dev/null and b/testing/tests/swanctl/rw-ntru-bliss/hosts/dave/etc/swanctl/x509/daveCert.der differ
diff --git a/testing/tests/swanctl/rw-ntru-bliss/hosts/dave/etc/swanctl/x509ca/strongswan_blissCert.der b/testing/tests/swanctl/rw-ntru-bliss/hosts/dave/etc/swanctl/x509ca/strongswan_blissCert.der
new file mode 100644
index 0000000..fdfd39f
Binary files /dev/null and b/testing/tests/swanctl/rw-ntru-bliss/hosts/dave/etc/swanctl/x509ca/strongswan_blissCert.der differ
diff --git a/testing/tests/swanctl/rw-ntru-bliss/hosts/moon/etc/strongswan.conf b/testing/tests/swanctl/rw-ntru-bliss/hosts/moon/etc/strongswan.conf
new file mode 100644
index 0000000..ec18f44
--- /dev/null
+++ b/testing/tests/swanctl/rw-ntru-bliss/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,14 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce aes sha1 sha2 sha3 hmac ntru bliss x509 revocation pem pkcs1 curl vici kernel-netlink socket-default updown
+
+  send_vendor_id = yes
+  fragment_size = 1500
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds
+    pools = /usr/local/sbin/swanctl --load-pools 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/rw-ntru-bliss/hosts/moon/etc/swanctl/bliss/moonKey.der b/testing/tests/swanctl/rw-ntru-bliss/hosts/moon/etc/swanctl/bliss/moonKey.der
new file mode 100644
index 0000000..c989f91
Binary files /dev/null and b/testing/tests/swanctl/rw-ntru-bliss/hosts/moon/etc/swanctl/bliss/moonKey.der differ
diff --git a/testing/tests/swanctl/rw-ntru-bliss/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-ntru-bliss/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..2e1ae8d
--- /dev/null
+++ b/testing/tests/swanctl/rw-ntru-bliss/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,34 @@
+connections {
+
+   rw {
+      local_addrs  = 192.168.0.1
+      pools = rw_pool
+
+      local {
+         auth = bliss-sha512 
+         certs = moonCert.der
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = pubkey
+         revocation = strict
+      }
+      children {
+         net {
+            local_ts  = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128-sha256-ntru128,aes192-sha384-ntru192
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-ntru128,aes192-sha384-ntru192
+      fragmentation = yes
+   }
+}
+
+pools {
+   rw_pool {
+      addrs = 10.3.0.0/28
+   }
+}
diff --git a/testing/tests/swanctl/rw-ntru-bliss/hosts/moon/etc/swanctl/x509/moonCert.der b/testing/tests/swanctl/rw-ntru-bliss/hosts/moon/etc/swanctl/x509/moonCert.der
new file mode 100644
index 0000000..d0ea364
Binary files /dev/null and b/testing/tests/swanctl/rw-ntru-bliss/hosts/moon/etc/swanctl/x509/moonCert.der differ
diff --git a/testing/tests/swanctl/rw-ntru-bliss/hosts/moon/etc/swanctl/x509ca/strongswan_blissCert.der b/testing/tests/swanctl/rw-ntru-bliss/hosts/moon/etc/swanctl/x509ca/strongswan_blissCert.der
new file mode 100644
index 0000000..fdfd39f
Binary files /dev/null and b/testing/tests/swanctl/rw-ntru-bliss/hosts/moon/etc/swanctl/x509ca/strongswan_blissCert.der differ
diff --git a/testing/tests/swanctl/rw-ntru-bliss/posttest.dat b/testing/tests/swanctl/rw-ntru-bliss/posttest.dat
new file mode 100644
index 0000000..58d5b86
--- /dev/null
+++ b/testing/tests/swanctl/rw-ntru-bliss/posttest.dat
@@ -0,0 +1,9 @@
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
+moon::iptables-restore < /etc/iptables.flush
+carol::iptables-restore < /etc/iptables.flush
+dave::iptables-restore < /etc/iptables.flush
+moon::cd /etc/swanctl;  rm bliss/* x509/moonCert.der  x509ca/strongswan_blissCert.der
+carol::cd /etc/swanctl; rm bliss/* x509/carolCert.der x509ca/strongswan_blissCert.der
+dave::cd /etc/swanctl;  rm bliss/* x509/daveCert.der  x509ca/strongswan_blissCert.der
diff --git a/testing/tests/swanctl/rw-ntru-bliss/pretest.dat b/testing/tests/swanctl/rw-ntru-bliss/pretest.dat
new file mode 100644
index 0000000..a550a2f
--- /dev/null
+++ b/testing/tests/swanctl/rw-ntru-bliss/pretest.dat
@@ -0,0 +1,14 @@
+moon::iptables-restore < /etc/iptables.rules
+carol::iptables-restore < /etc/iptables.rules
+dave::iptables-restore < /etc/iptables.rules
+moon::cd /etc/swanctl;  rm rsa/* x509/moonCert.pem  x509ca/strongswanCert.pem
+carol::cd /etc/swanctl; rm rsa/* x509/carolCert.pem x509ca/strongswanCert.pem
+dave::cd /etc/swanctl;  rm rsa/* x509/daveCert.pem  x509ca/strongswanCert.pem
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
+carol::expect-connection home
+carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/rw-ntru-bliss/test.conf b/testing/tests/swanctl/rw-ntru-bliss/test.conf
new file mode 100644
index 0000000..a542d03
--- /dev/null
+++ b/testing/tests/swanctl/rw-ntru-bliss/test.conf
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# guest instances used for this test
+
+# All guest instances that are required for this test
+#
+VIRTHOSTS="alice moon carol winnetou dave"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-m-c-w-d.png"
+
+# Guest instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="moon alice"
+
+# Guest instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon carol dave"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/swanctl/rw-psk-fqdn/evaltest.dat b/testing/tests/swanctl/rw-psk-fqdn/evaltest.dat
index bb5e08b..a184ee9 100755
--- a/testing/tests/swanctl/rw-psk-fqdn/evaltest.dat
+++ b/testing/tests/swanctl/rw-psk-fqdn/evaltest.dat
@@ -1,7 +1,7 @@
-carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/16]::YES
-dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.0/16]::YES
-moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]
-moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/16]::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.0/16]::YES
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]
 alice::ping -c 1 192.168.0.100::64 bytes from 192.168.0.100: icmp_req=1::YES
 alice::ping -c 1 192.168.0.200::64 bytes from 192.168.0.200: icmp_req=1::YES
 moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
diff --git a/testing/tests/swanctl/rw-psk-fqdn/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-psk-fqdn/hosts/carol/etc/swanctl/swanctl.conf
index c113620..9bf759e 100755
--- a/testing/tests/swanctl/rw-psk-fqdn/hosts/carol/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/rw-psk-fqdn/hosts/carol/etc/swanctl/swanctl.conf
@@ -16,17 +16,12 @@ connections {
          home {
             remote_ts = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
 
diff --git a/testing/tests/swanctl/rw-psk-fqdn/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-psk-fqdn/hosts/dave/etc/swanctl/swanctl.conf
index 928fd04..1f2beef 100755
--- a/testing/tests/swanctl/rw-psk-fqdn/hosts/dave/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/rw-psk-fqdn/hosts/dave/etc/swanctl/swanctl.conf
@@ -16,17 +16,12 @@ connections {
          home {
             remote_ts = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
 
diff --git a/testing/tests/swanctl/rw-psk-fqdn/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-psk-fqdn/hosts/moon/etc/swanctl/swanctl.conf
index 8cae3e8..7138b5d 100755
--- a/testing/tests/swanctl/rw-psk-fqdn/hosts/moon/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/rw-psk-fqdn/hosts/moon/etc/swanctl/swanctl.conf
@@ -14,17 +14,12 @@ connections {
          net {
             local_ts  = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
 
diff --git a/testing/tests/swanctl/rw-psk-fqdn/pretest.dat b/testing/tests/swanctl/rw-psk-fqdn/pretest.dat
index d55df40..519b168 100755
--- a/testing/tests/swanctl/rw-psk-fqdn/pretest.dat
+++ b/testing/tests/swanctl/rw-psk-fqdn/pretest.dat
@@ -7,6 +7,8 @@ dave::cd /etc/swanctl; rm rsa/* x509/* x509ca/*
 moon::service charon start 2> /dev/null
 carol::service charon start 2> /dev/null
 dave::service charon start 2> /dev/null
-moon::sleep 1
+moon::expect-connection rw
+carol::expect-connection home
 carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
 dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/rw-psk-ikev1/description.txt b/testing/tests/swanctl/rw-psk-ikev1/description.txt
new file mode 100755
index 0000000..73aac6f
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ikev1/description.txt
@@ -0,0 +1,16 @@
+The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each 
+to gateway <b>moon</b>. The IKEv1 main mode authentication is based on
+<b>pre-shared keys</b> and <b>IPv4 address</b> identities.
+On the gateway two connections with differing parameters are defined:
+One for peers from the <b>192.168.0.96/28</b> subnet and one for peers from
+the range <b>192.168.0.150-192.168.0.200</b>.
+<p/>
+On the gateway for different shared keys are defined for the following
+hierarchcal peer address ranges: <b>0.0.0.0/0 0::0/0</b>,
+<b>192.168.0.96/28</b>, <b>192.168.0.150-192.168.0.200</b> and
+<b>192.168.0.200</b>. Client <b>carol</b> uses the first and client <b>dave</b>
+the fourth PSK.
+<p/>
+Upon the successful establishment of the IPsec tunnels, <b>carol</b> pings the
+client <b>alice</b> and <b>dave</b> the client <b>venus</b> lying in two different
+subnets behind the gateway <b>moon</b>.
diff --git a/testing/tests/swanctl/rw-psk-ikev1/evaltest.dat b/testing/tests/swanctl/rw-psk-ikev1/evaltest.dat
new file mode 100755
index 0000000..96d74c8
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ikev1/evaltest.dat
@@ -0,0 +1,14 @@
+dave::cat /var/log/daemon.log::updown approximates remote TS 10.1.0.17..10.1.0.20 by next larger subnet::YES
+moon::cat /var/log/daemon.log::updown approximates local TS 10.1.0.17..10.1.0.20 by next larger subnet::YES
+alice::ping -c 1 192.168.0.100::64 bytes from 192.168.0.100: icmp_req=1::YES
+venus::ping -c 1 192.168.0.200::64 bytes from 192.168.0.200: icmp_req=1::YES
+alice::ping -c 1 -W 1 192.168.0.200::64 bytes from 192.168.0.200: icmp_req=1::NO
+venus::ping -c 1 -W 1 192.168.0.100::64 bytes from 192.168.0.100: icmp_req=1::NO
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=1 state=ESTABLISHED local-host=192.168.0.100 local-port=500 local-id=192.168.0.100 remote-host=192.168.0.1 remote-port=500 remote-id=192.168.0.1 initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/28]::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=1 state=ESTABLISHED local-host=192.168.0.200 local-port=500 local-id=192.168.0.200 remote-host=192.168.0.1 remote-port=500 remote-id=192.168.0.1 initiator=yes.*encr-alg=AES_CBC encr-keysize=192 integ-alg=HMAC_SHA2_384_192 prf-alg=PRF_HMAC_SHA2_384 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=192.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.17..10.1.0.20]::YES
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw-1.*version=1 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=192.168.0.1 remote-host=192.168.0.100 remote-port=500 remote-id=192.168.0.100.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net-1.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/28] remote-ts=\[192.168.0.100/32]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw-2.*version=1 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=192.168.0.1 remote-host=192.168.0.200 remote-port=500 remote-id=192.168.0.200.*encr-alg=AES_CBC encr-keysize=192 integ-alg=HMAC_SHA2_384_192 prf-alg=PRF_HMAC_SHA2_384 dh-group=MODP_3072.*child-sas.*net-2.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=192.*local-ts=\[10.1.0.17..10.1.0.20] remote-ts=\[192.168.0.200/32]
+moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
+moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
+moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES
+moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/swanctl/rw-psk-ikev1/hosts/carol/etc/strongswan.conf b/testing/tests/swanctl/rw-psk-ikev1/hosts/carol/etc/strongswan.conf
new file mode 100755
index 0000000..8c0f03f
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ikev1/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,23 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 x509 revocation constraints pubkey openssl random 
+}
+
+charon {
+  load = sha1 sha2 md5 aes des hmac gmp random nonce kernel-netlink socket-default updown vici
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      cfg = 1 
+      ike = 1 
+    }
+  }
+}
diff --git a/testing/tests/swanctl/rw-psk-ikev1/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-psk-ikev1/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..dcfcd0b
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ikev1/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,33 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = psk
+      }
+      remote {
+         auth = psk
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/28 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp2048
+         }
+      }
+      version = 1
+      proposals = aes128-sha256-modp2048
+   }
+}
+
+secrets {
+
+   ike-moon {
+      id = 192.168.0.1
+      # hex value equal to base64 0sFpZAZqEN6Ti9sqt4ZP5EWcqx
+      secret = 0x16964066a10de938bdb2ab7864fe4459cab1
+   }
+}
diff --git a/testing/tests/swanctl/rw-psk-ikev1/hosts/dave/etc/strongswan.conf b/testing/tests/swanctl/rw-psk-ikev1/hosts/dave/etc/strongswan.conf
new file mode 100755
index 0000000..df1424d
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ikev1/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,23 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 x509 revocation constraints pubkey openssl random 
+}
+
+charon {
+  load = sha1 sha2 md5 aes des hmac gmp random nonce kernel-netlink socket-default updown vici
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      cfg = 1
+      ike = 1 
+    }
+  }
+}
diff --git a/testing/tests/swanctl/rw-psk-ikev1/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-psk-ikev1/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..8cd79ea
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ikev1/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,32 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = psk 
+      }
+      remote {
+         auth = psk 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.17-10.1.0.20
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes192gcm128-modp3072
+         }
+      }
+      version = 1 
+      proposals = aes192-sha384-modp3072
+   }
+}
+
+secrets {
+
+   ike-moon {
+      id = 192.168.0.1
+      secret = 0sjVzONCF02ncsgiSlmIXeqhGN
+   }
+}
diff --git a/testing/tests/swanctl/rw-psk-ikev1/hosts/moon/etc/strongswan.conf b/testing/tests/swanctl/rw-psk-ikev1/hosts/moon/etc/strongswan.conf
new file mode 100755
index 0000000..5f21901
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ikev1/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,23 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 x509 revocation constraints pubkey openssl random 
+}
+
+charon {
+  load = sha1 sha2 md5 aes des hmac gmp random nonce kernel-netlink socket-default updown vici
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      cfg = 1 
+      ike = 1 
+    }
+  }   
+}
diff --git a/testing/tests/swanctl/rw-psk-ikev1/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-psk-ikev1/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..be1bf8a
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ikev1/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,67 @@
+connections {
+
+   rw-1 {
+      local_addrs  = 192.168.0.1
+      remote_addrs = 192.168.0.96/28
+
+      local {
+         auth = psk 
+      }
+      remote {
+         auth = psk 
+      }
+      children {
+         net-1 {
+            local_ts  = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp2048
+         }
+      }
+      version = 1 
+      proposals = aes128-sha256-modp2048
+   }
+
+   rw-2 {
+      local_addrs  = 192.168.0.1
+      remote_addrs = 192.168.0.150-192.168.0.200
+
+      local {
+         auth = psk
+      }
+      remote {
+         auth = psk
+      }
+      children {
+         net-2 {
+            local_ts  = 10.1.0.17-10.1.0.20
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes192gcm128-modp3072
+         }
+      }
+      version = 1
+      proposals = aes192-sha384-modp3072
+   }
+}
+
+
+secrets {
+
+   ike-any {
+      id = 0.0.0.0/0 0::0/0
+      secret = 0soBAJZLI7Bwwi61Rl113FqD/3
+   }
+   ike-rw-1 {
+      id = 192.168.0.96/28
+      secret = 0sFpZAZqEN6Ti9sqt4ZP5EWcqx
+   }
+   ike-rw-2 {
+      id = 192.168.0.150-192.168.0.200
+      secret = 0s8qPdxyhDeGfk1l211cS8urXc
+   }
+   ike-dave {
+      id = 192.168.0.200
+      secret = 0sjVzONCF02ncsgiSlmIXeqhGN
+   }
+}
diff --git a/testing/tests/swanctl/rw-psk-ikev1/posttest.dat b/testing/tests/swanctl/rw-psk-ikev1/posttest.dat
new file mode 100755
index 0000000..d7107cc
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ikev1/posttest.dat
@@ -0,0 +1,8 @@
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
+moon::iptables-restore < /etc/iptables.flush
+carol::iptables-restore < /etc/iptables.flush
+dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/swanctl/rw-psk-ikev1/pretest.dat b/testing/tests/swanctl/rw-psk-ikev1/pretest.dat
new file mode 100755
index 0000000..3393f51
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ikev1/pretest.dat
@@ -0,0 +1,15 @@
+moon::iptables-restore < /etc/iptables.rules
+carol::iptables-restore < /etc/iptables.rules
+dave::iptables-restore < /etc/iptables.rules
+moon::cd /etc/swanctl; rm rsa/* x509/* x509ca/*
+carol::cd /etc/swanctl; rm rsa/* x509/* x509ca/*
+dave::cd /etc/swanctl; rm rsa/* x509/* x509ca/*
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection net-1
+moon::expect-connection net-2 
+carol::expect-connection home
+carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/rw-psk-ikev1/test.conf b/testing/tests/swanctl/rw-psk-ikev1/test.conf
new file mode 100755
index 0000000..b8048b4
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ikev1/test.conf
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# guest instances used for this test
+
+# All guest instances that are required for this test
+#
+VIRTHOSTS="alice venus moon carol winnetou dave"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-v-m-c-w-d.png"
+
+# Guest instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="moon"
+
+# Guest instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon carol dave"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/swanctl/rw-psk-ipv4/evaltest.dat b/testing/tests/swanctl/rw-psk-ipv4/evaltest.dat
index 142e88e..7acb15a 100755
--- a/testing/tests/swanctl/rw-psk-ipv4/evaltest.dat
+++ b/testing/tests/swanctl/rw-psk-ipv4/evaltest.dat
@@ -1,7 +1,7 @@
-carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-id=192.168.0.100 remote-host=192.168.0.1 remote-id=192.168.0.1 initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/16]::YES
-dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-id=192.168.0.200 remote-host=192.168.0.1 remote-id=192.168.0.1 initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.0/16]::YES
-moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=192.168.0.1 remote-host=192.168.0.100 remote-id=192.168.0.100.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]
-moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=192.168.0.1 remote-host=192.168.0.200 remote-id=192.168.0.200.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_2048.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=192.168.0.100 remote-host=192.168.0.1 remote-port=4500 remote-id=192.168.0.1 initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/16]::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=192.168.0.200 remote-host=192.168.0.1 remote-port=4500 remote-id=192.168.0.1 initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.0/16]::YES
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=192.168.0.1 remote-host=192.168.0.100 remote-port=4500 remote-id=192.168.0.100.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=192.168.0.1 remote-host=192.168.0.200 remote-port=4500 remote-id=192.168.0.200.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]
 alice::ping -c 1 192.168.0.100::64 bytes from 192.168.0.100: icmp_req=1::YES
 alice::ping -c 1 192.168.0.200::64 bytes from 192.168.0.200: icmp_req=1::YES
 moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
diff --git a/testing/tests/swanctl/rw-psk-ipv4/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-psk-ipv4/hosts/carol/etc/swanctl/swanctl.conf
index bd00fc3..8b3863b 100755
--- a/testing/tests/swanctl/rw-psk-ipv4/hosts/carol/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/rw-psk-ipv4/hosts/carol/etc/swanctl/swanctl.conf
@@ -16,17 +16,12 @@ connections {
          home {
             remote_ts = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
 
diff --git a/testing/tests/swanctl/rw-psk-ipv4/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-psk-ipv4/hosts/dave/etc/swanctl/swanctl.conf
index b30790b..83f3c0a 100755
--- a/testing/tests/swanctl/rw-psk-ipv4/hosts/dave/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/rw-psk-ipv4/hosts/dave/etc/swanctl/swanctl.conf
@@ -16,17 +16,12 @@ connections {
          home {
             remote_ts = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
 
diff --git a/testing/tests/swanctl/rw-psk-ipv4/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-psk-ipv4/hosts/moon/etc/swanctl/swanctl.conf
index 098b3c0..9b4f7ce 100755
--- a/testing/tests/swanctl/rw-psk-ipv4/hosts/moon/etc/swanctl/swanctl.conf
+++ b/testing/tests/swanctl/rw-psk-ipv4/hosts/moon/etc/swanctl/swanctl.conf
@@ -13,17 +13,12 @@ connections {
          net {
             local_ts  = 10.1.0.0/16 
 
-            start_action = none
             updown = /usr/local/libexec/ipsec/_updown iptables
-            rekey_time = 10m 
-            esp_proposals = aes128gcm128-modp2048
+            esp_proposals = aes128gcm128-modp3072
          }
       }
-
       version = 2
-      reauth_time = 60m
-      rekey_time =  20m
-      proposals = aes128-sha256-modp2048
+      proposals = aes128-sha256-modp3072
    }
 }
 
diff --git a/testing/tests/swanctl/rw-psk-ipv4/pretest.dat b/testing/tests/swanctl/rw-psk-ipv4/pretest.dat
index d55df40..519b168 100755
--- a/testing/tests/swanctl/rw-psk-ipv4/pretest.dat
+++ b/testing/tests/swanctl/rw-psk-ipv4/pretest.dat
@@ -7,6 +7,8 @@ dave::cd /etc/swanctl; rm rsa/* x509/* x509ca/*
 moon::service charon start 2> /dev/null
 carol::service charon start 2> /dev/null
 dave::service charon start 2> /dev/null
-moon::sleep 1
+moon::expect-connection rw
+carol::expect-connection home
 carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
 dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/rw-pubkey-anon/description.txt b/testing/tests/swanctl/rw-pubkey-anon/description.txt
new file mode 100755
index 0000000..4ccc06a
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/description.txt
@@ -0,0 +1,9 @@
+The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each 
+to gateway <b>moon</b>. The authentication is based on <b>raw public keys</b>
+and IKEv2 key IDs. Gateway <b>moon</b> accepts all peers possessing a
+public key a copy of which is stored in the <b>/etc/swanctl/pubkey</b> directory.
+<p/>
+Upon the successful establishment of the IPsec tunnels, the updown script
+automatically inserts iptables-based firewall rules that let pass the tunneled traffic.
+In order to test both tunnel and firewall, both <b>carol</b> and <b>dave</b> ping
+the client <b>alice</b> behind the gateway <b>moon</b>.
diff --git a/testing/tests/swanctl/rw-pubkey-anon/evaltest.dat b/testing/tests/swanctl/rw-pubkey-anon/evaltest.dat
new file mode 100755
index 0000000..f0cd34c
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/evaltest.dat
@@ -0,0 +1,10 @@
+alice::ping -c 1 192.168.0.100::64 bytes from 192.168.0.100: icmp_req=1::YES
+alice::ping -c 1 192.168.0.200::64 bytes from 192.168.0.200: icmp_req=1::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=0d:36:.*:cc:90 remote-host=192.168.0.1 remote-port=4500 remote-id=42:91:.*:f7:60 initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/16]::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=67:f6:.*:40:80 remote-host=192.168.0.1 remote-port=4500 remote-id=42:91:.*:f7:60 initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.0/16]::YES
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=42:91:.*:f7:60 remote-host=192.168.0.100 remote-port=4500 remote-id=0d:36:.*:cc:90.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*net.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]::YES
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=42:91:.*:f7:60 remote-host=192.168.0.200 remote-port=4500 remote-id=67:f6:.*:40:80.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*net.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]::YES
+moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
+moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
+moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES
+moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/swanctl/rw-pubkey-anon/hosts/carol/etc/strongswan.conf b/testing/tests/swanctl/rw-pubkey-anon/hosts/carol/etc/strongswan.conf
new file mode 100755
index 0000000..dc166b5
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,14 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 pubkey openssl random 
+}
+
+charon {
+  load = random nonce openssl pem pkcs1 pubkey kernel-netlink socket-default updown vici 
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/rw-pubkey-anon/hosts/carol/etc/swanctl/pubkey/carolPub.pem b/testing/tests/swanctl/rw-pubkey-anon/hosts/carol/etc/swanctl/pubkey/carolPub.pem
new file mode 100644
index 0000000..8fdc45a
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/hosts/carol/etc/swanctl/pubkey/carolPub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt/PUNxfK3+w4AuLUhn9F
+y49rmb7h+JJJPbBVZauXDeFSN6LAt+Cguu0poZfiL4C3zZmiXaZ1sRcWk772rFeW
+I/a7R97Go/iYG5m6zcQsDzYQ4vSVDZqECLw7epp+QMwFKC+h4mkTA17TRSCHneDu
+FPt3Dy1KBw8apCRa60ggpP1Pp78dsc2NG1iXD1mUeynyBJiOD9Dq9Xqh+2254xQP
+01G/zDZjvqudFGZQZ/caU0UWaDFme0IlG5iW2fFXtVwIWimnJq5i398+aMDFs9G6
+EcppyfMjOrzcjF/l9KMxOWW4YJ9YVf80YQ1dqYGoKGREsea4Ic17HFGn2zYXVLXS
+EQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/rw-pubkey-anon/hosts/carol/etc/swanctl/pubkey/moonPub.pem b/testing/tests/swanctl/rw-pubkey-anon/hosts/carol/etc/swanctl/pubkey/moonPub.pem
new file mode 100644
index 0000000..94fadce
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/hosts/carol/etc/swanctl/pubkey/moonPub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApHwF+sUXQdH+WwYzdPMz
+pjuwhGGvHgsmBah1IQsPsddL9gZygerzpTM1vvQ4kbRuvE3SZWLf9uKEbiQV9IAB
+r87L9JAva56EHIAiUMuG8WizVbIKIhQlZc8S2mIwAW0Jc6EmnoJv9j6F/tVD9+6x
+vMJbwHLi0h7BUO9tBVLPy72YeGNBY6Cob4CrOuFOJyACezJ7i9vZ+XzOfnXpu7qL
+0DgYP/n2maPEJGEivTFunkJD/mJ8DecyLTQcchsCj2118BMuf2qjVn4UWPCBBuhy
+YK5wsATB1ANeAtlFfgH+wsuHjZwtTJru05lGHBZ3F2hZ9PO68hVHbIZZj6SB8X47
+nwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/rw-pubkey-anon/hosts/carol/etc/swanctl/rsa/carolKey.pem b/testing/tests/swanctl/rw-pubkey-anon/hosts/carol/etc/swanctl/rsa/carolKey.pem
new file mode 100644
index 0000000..1454ec5
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/hosts/carol/etc/swanctl/rsa/carolKey.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,7E1D40A7901772BA4D22AF58AA2DC76F
+
+1jt4EsxtHvgpSLN8PA/kSVKgoAsBEBQb8RK6VGnZywMCnpJdLKdPisGGYKNPg53b
+/0AFBmQVE60M8icbSAIUrAtyKxaBkoc9A7ibNCjobi0UzXTm3GcZZ1EC4/lE9PQZ
+/2FbcPgQWN3kZraZDkeP9XBXl6PorES8xvQUxJ9pd4hL7/c28fIApGhEimkIZO8o
+Qb7bR2cNCLYQAR6PeDoqhV39gvWoh77wp1WB3tQVbkS6MI/xl3wY2QVdq3Sbszh+
+f6lDU/SZS8BU0f44FRoInPp0GasgJ7MCiuEIshjuNPa50QkMcnNJsSgVEuw2hjN6
+LvAXx7vPt9pKpQfnu7YSJUsXDYN6PyXt7sZ8hDqraYIcI6eMpEBaTpItPSV2eckv
+06KC24Oa66E1yufNFAY49S2OY+pJA0W5zmcCqCjdrfJ+wNQYKZpbrfGz4VRzlFJC
+e3VkmAFwA5rcZdlp/mU2XREy+TaWsHMnpL0NcMHGmsfkTgaJIkRWalrdxlNTeitr
+3boNHWk0ESyMcBYRpM3eNXsGpiYy93u0bhrPbnqJsV6miKqpbs1aBNjlJ9s1Y2fC
+sko5/v7uMjb5tLF3lWQZfTu+bYtpGxFrqHJjhd8yd4gL1cFi30JcjczhwRY3Dily
+c0BFekMGmPc1djn6tfIFu13X9xTxyidCpVaT9UGnOaQs9OF1u8XAnZDaQgPwjLiy
+UlOE8xQ60LrhWLD582FsFnZz56bZ+QOQRWDMsB8nJeqnFXKfcRlnr0qlG6lTfA8h
+XkK/qGpdVvivS+CpbhVP6ixdEfa91Rx4NjLj53LGqOYwFEkM/OAIuMJetBfx3v9T
+iQfv594KE32nv9besnKlmJr2cGQWBYg1pUOtFj/aZ00yuXacv8qwzbrt4xGGDYGO
+Aj5Yf93UEcVkTySO1xJ1yiC6GJv1lLm0i5StwykHypxFijKe/zOpgtHVa5v5igjO
+v6cfhfJGGgIPTYrtt+EDKXcayvy2e2U/3HYVCHYiiMPX8AvP/R6m7MGrzYxm/WyO
+t68EWXSDLfuR3qcIlpP4aSBxuSpKhY/dIkS/beKZ7Njx1s4jSuYDMbKuuCRFSU2H
+8ISHS0kh3FetiS8IyIYzxab+KQZwnVtiGj4oaAhgFTIIoH26Fv5+xka74JdzOSUA
+jR9puKuxaegVWQVBx4cCyg6hAdewRm64PAcbApZWrPvMPBfTZFnXeifmaurcdK8p
+p/1eLrrPnNM6+Fh6lcKdX74yHPz3eWP3K1njZegzWnChhEWElPhJr6qYNQjd+lAS
+7650RJ3CJLUxBffnRR9nTArxFNI5jGWg/plLJTaRT5x5qg1dGNMqntpoeiY++Ttk
+GFDGVIOICBze6SOvzkZBbuXLJSWmWj5g9J2cYsLoOvlwsDT7FzKl8p6VY4V+SQb+
+4PN8qZWmOeczaLEhZ1QLmTKFpz9+wUZsXeBd1s78bWJR0zhraMPa0UJ9GBGq6uQ0
+yZ4Xm5KHKcgoewCUQMekU9ECsmR5NuC7VFDaa1OdPEVnEYR1xtaWUY0lYKOiixnd
++85fSq/yAXI/r0O4ISA55o9y1kDqVibTwJacb6xXGg8dHSH+TtigwD8fK9mekkDC
+-----END RSA PRIVATE KEY-----
diff --git a/testing/tests/swanctl/rw-pubkey-anon/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-pubkey-anon/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..f1a074f
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,34 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = pubkey
+         pubkeys = carolPub.pem
+      }
+      remote {
+         auth = pubkey
+         pubkeys = moonPub.pem 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-ecp256
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-ecp256
+   }
+}
+
+secrets {
+
+   rsa-carol {
+      file = carolKey.pem
+      secret = "nH5ZQEWtku0RJEZ6"
+   }
+}
diff --git a/testing/tests/swanctl/rw-pubkey-anon/hosts/dave/etc/strongswan.conf b/testing/tests/swanctl/rw-pubkey-anon/hosts/dave/etc/strongswan.conf
new file mode 100755
index 0000000..dc166b5
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,14 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 pubkey openssl random 
+}
+
+charon {
+  load = random nonce openssl pem pkcs1 pubkey kernel-netlink socket-default updown vici 
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/rw-pubkey-anon/hosts/dave/etc/swanctl/pubkey/davePub.pem b/testing/tests/swanctl/rw-pubkey-anon/hosts/dave/etc/swanctl/pubkey/davePub.pem
new file mode 100644
index 0000000..154ac50
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/hosts/dave/etc/swanctl/pubkey/davePub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1jzcTcWEzV+14gWt0dJC
+Ew8ZYpfWCD4lTz0grXvhf+T9gMHx9vx3SiZvAq+CBTuTkpsBydpUEbQC9GZv6qRd
+1FmIQCUk6pHZit+UH44w3tuc+YNB6QjT1PMMm31rULX14jGZQnaHYN4MASfGumnX
+CwqdYF3jwx5iGOQAStGHHwDxmUFuR3IZAkP7Lwa2nSJZLivPxqIZDS9hL4/0NWQw
+ltsaGXZqrBVj4Xffn/8tUbbjj7LNdN/WjxovA+XX48dyBq834zvrpjduojlgeCHY
+IQlMJoF/jOihMFJDpOvVxDkH/9XnX0nXH+6H//YKkRBdsVgWJTeQuZNM/P2lyZ5W
+QwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/rw-pubkey-anon/hosts/dave/etc/swanctl/pubkey/moonPub.pem b/testing/tests/swanctl/rw-pubkey-anon/hosts/dave/etc/swanctl/pubkey/moonPub.pem
new file mode 100644
index 0000000..94fadce
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/hosts/dave/etc/swanctl/pubkey/moonPub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApHwF+sUXQdH+WwYzdPMz
+pjuwhGGvHgsmBah1IQsPsddL9gZygerzpTM1vvQ4kbRuvE3SZWLf9uKEbiQV9IAB
+r87L9JAva56EHIAiUMuG8WizVbIKIhQlZc8S2mIwAW0Jc6EmnoJv9j6F/tVD9+6x
+vMJbwHLi0h7BUO9tBVLPy72YeGNBY6Cob4CrOuFOJyACezJ7i9vZ+XzOfnXpu7qL
+0DgYP/n2maPEJGEivTFunkJD/mJ8DecyLTQcchsCj2118BMuf2qjVn4UWPCBBuhy
+YK5wsATB1ANeAtlFfgH+wsuHjZwtTJru05lGHBZ3F2hZ9PO68hVHbIZZj6SB8X47
+nwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/rw-pubkey-anon/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-pubkey-anon/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..4383ab8
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,26 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = pubkey
+         pubkeys = davePub.pem
+      }
+      remote {
+         auth = pubkey
+         pubkeys = moonPub.pem
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-ecp256
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-ecp256
+   }
+}
diff --git a/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/strongswan.conf b/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/strongswan.conf
new file mode 100755
index 0000000..720e903
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,14 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 x509 revocation constraints pubkey openssl random 
+}
+
+charon {
+  load = random nonce openssl pem pkcs1 pubkey kernel-netlink socket-default updown vici 
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/swanctl/pubkey/carolPub.pem b/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/swanctl/pubkey/carolPub.pem
new file mode 100644
index 0000000..8fdc45a
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/swanctl/pubkey/carolPub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt/PUNxfK3+w4AuLUhn9F
+y49rmb7h+JJJPbBVZauXDeFSN6LAt+Cguu0poZfiL4C3zZmiXaZ1sRcWk772rFeW
+I/a7R97Go/iYG5m6zcQsDzYQ4vSVDZqECLw7epp+QMwFKC+h4mkTA17TRSCHneDu
+FPt3Dy1KBw8apCRa60ggpP1Pp78dsc2NG1iXD1mUeynyBJiOD9Dq9Xqh+2254xQP
+01G/zDZjvqudFGZQZ/caU0UWaDFme0IlG5iW2fFXtVwIWimnJq5i398+aMDFs9G6
+EcppyfMjOrzcjF/l9KMxOWW4YJ9YVf80YQ1dqYGoKGREsea4Ic17HFGn2zYXVLXS
+EQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/swanctl/pubkey/davePub.pem b/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/swanctl/pubkey/davePub.pem
new file mode 100644
index 0000000..154ac50
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/swanctl/pubkey/davePub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1jzcTcWEzV+14gWt0dJC
+Ew8ZYpfWCD4lTz0grXvhf+T9gMHx9vx3SiZvAq+CBTuTkpsBydpUEbQC9GZv6qRd
+1FmIQCUk6pHZit+UH44w3tuc+YNB6QjT1PMMm31rULX14jGZQnaHYN4MASfGumnX
+CwqdYF3jwx5iGOQAStGHHwDxmUFuR3IZAkP7Lwa2nSJZLivPxqIZDS9hL4/0NWQw
+ltsaGXZqrBVj4Xffn/8tUbbjj7LNdN/WjxovA+XX48dyBq834zvrpjduojlgeCHY
+IQlMJoF/jOihMFJDpOvVxDkH/9XnX0nXH+6H//YKkRBdsVgWJTeQuZNM/P2lyZ5W
+QwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/swanctl/pubkey/moonPub.pem b/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/swanctl/pubkey/moonPub.pem
new file mode 100644
index 0000000..94fadce
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/swanctl/pubkey/moonPub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApHwF+sUXQdH+WwYzdPMz
+pjuwhGGvHgsmBah1IQsPsddL9gZygerzpTM1vvQ4kbRuvE3SZWLf9uKEbiQV9IAB
+r87L9JAva56EHIAiUMuG8WizVbIKIhQlZc8S2mIwAW0Jc6EmnoJv9j6F/tVD9+6x
+vMJbwHLi0h7BUO9tBVLPy72YeGNBY6Cob4CrOuFOJyACezJ7i9vZ+XzOfnXpu7qL
+0DgYP/n2maPEJGEivTFunkJD/mJ8DecyLTQcchsCj2118BMuf2qjVn4UWPCBBuhy
+YK5wsATB1ANeAtlFfgH+wsuHjZwtTJru05lGHBZ3F2hZ9PO68hVHbIZZj6SB8X47
+nwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/swanctl/pubkey/sunPub.pem b/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/swanctl/pubkey/sunPub.pem
new file mode 100644
index 0000000..5254ed1
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/swanctl/pubkey/sunPub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxyIgBH1KWzMMmEYS1Gr1
+4IUBg120vdsLuNwQuzu22qIHnWIBSB2L0lkLOBY0AYd3wi9ENXnb0MOJTFfE5YJ1
+gpSZCnS3m9HqgTmmYeZ3mVxSC4TJWu2oVKvosxSo5fAVvjVVQ089HtjIsx2BR/0q
+LQ9lZ2dUtUSn9kohjU5qpktOfJ9XuTQj9dBfa5bpQMJoLUBAGWPMR+sPaBRwb34U
+ulvmoOyIZTKGEsH6czUY0+dm8iUKmkP7S3fEQjzv56Dk3zrJcFy7ij87uu9Wk/Xs
+auHAq5jHREcMFJwEOj9ZE0Q6ufz9D2NBSWvLTr7QKFVhj5HfbyUcAGRqgf+sHrkl
+IQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..a068c7f
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,24 @@
+connections {
+
+   rw {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey
+         pubkeys = moonPub.pem
+      }
+      remote {
+         auth = pubkey
+      }
+      children {
+         net {
+            local_ts  = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-ecp256
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-ecp256
+   }
+}
diff --git a/testing/tests/swanctl/rw-pubkey-anon/posttest.dat b/testing/tests/swanctl/rw-pubkey-anon/posttest.dat
new file mode 100755
index 0000000..48a4abe
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/posttest.dat
@@ -0,0 +1,11 @@
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
+moon::rm /etc/swanctl/pubkey/*
+carol::rm /etc/swanctl/pubkey/*
+dave::rm /etc/swanctl/pubkey/*
+moon::iptables-restore < /etc/iptables.flush
+carol::iptables-restore < /etc/iptables.flush
+dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/swanctl/rw-pubkey-anon/pretest.dat b/testing/tests/swanctl/rw-pubkey-anon/pretest.dat
new file mode 100755
index 0000000..5faf602
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/pretest.dat
@@ -0,0 +1,14 @@
+moon::iptables-restore < /etc/iptables.rules
+carol::iptables-restore < /etc/iptables.rules
+dave::iptables-restore < /etc/iptables.rules
+moon::cd /etc/swanctl; rm x509/* x509ca/*
+carol::cd /etc/swanctl; rm x509/* x509ca/*
+dave::cd /etc/swanctl; rm x509/* x509ca/*
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
+carol::expect-connection home
+carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/rw-pubkey-anon/test.conf b/testing/tests/swanctl/rw-pubkey-anon/test.conf
new file mode 100755
index 0000000..1227b9d
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-anon/test.conf
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# guest instances used for this test
+
+# All guest instances that are required for this test
+#
+VIRTHOSTS="alice moon carol winnetou dave"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-m-c-w-d.png"
+
+# Guest instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="moon"
+
+# Guest instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon carol dave"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/description.txt b/testing/tests/swanctl/rw-pubkey-keyid/description.txt
new file mode 100755
index 0000000..e813bbe
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/description.txt
@@ -0,0 +1,8 @@
+The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each 
+to gateway <b>moon</b>. The authentication is based on <b>raw public keys</b>
+and IKEv2 key IDs.
+<p/>
+Upon the successful establishment of the IPsec tunnels, the updown script
+automatically inserts iptables-based firewall rules that let pass the tunneled traffic.
+In order to test both tunnel and firewall, both <b>carol</b> and <b>dave</b> ping
+the client <b>alice</b> behind the gateway <b>moon</b>.
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/evaltest.dat b/testing/tests/swanctl/rw-pubkey-keyid/evaltest.dat
new file mode 100755
index 0000000..70905de
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/evaltest.dat
@@ -0,0 +1,10 @@
+alice::ping -c 1 192.168.0.100::64 bytes from 192.168.0.100: icmp_req=1::YES
+alice::ping -c 1 192.168.0.200::64 bytes from 192.168.0.200: icmp_req=1::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=0d:36:.*:cc:90 remote-host=192.168.0.1 remote-port=4500 remote-id=42:91:.*:f7:60 initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/16]::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=67:f6:.*:40:80 remote-host=192.168.0.1 remote-port=4500 remote-id=42:91:.*:f7:60 initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.0/16]::YES
+moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw-carol.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=42:91:.*:f7:60 remote-host=192.168.0.100 remote-port=4500 remote-id=0d:36:.*:cc:90.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*net.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]::YES
+moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw-dave.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=42:91:.*:f7:60 remote-host=192.168.0.200 remote-port=4500 remote-id=67:f6:.*:40:80.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*net.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]::YES
+moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
+moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
+moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES
+moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/hosts/carol/etc/strongswan.conf b/testing/tests/swanctl/rw-pubkey-keyid/hosts/carol/etc/strongswan.conf
new file mode 100755
index 0000000..dc166b5
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,14 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 pubkey openssl random 
+}
+
+charon {
+  load = random nonce openssl pem pkcs1 pubkey kernel-netlink socket-default updown vici 
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/hosts/carol/etc/swanctl/pubkey/carolPub.pem b/testing/tests/swanctl/rw-pubkey-keyid/hosts/carol/etc/swanctl/pubkey/carolPub.pem
new file mode 100644
index 0000000..8fdc45a
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/hosts/carol/etc/swanctl/pubkey/carolPub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt/PUNxfK3+w4AuLUhn9F
+y49rmb7h+JJJPbBVZauXDeFSN6LAt+Cguu0poZfiL4C3zZmiXaZ1sRcWk772rFeW
+I/a7R97Go/iYG5m6zcQsDzYQ4vSVDZqECLw7epp+QMwFKC+h4mkTA17TRSCHneDu
+FPt3Dy1KBw8apCRa60ggpP1Pp78dsc2NG1iXD1mUeynyBJiOD9Dq9Xqh+2254xQP
+01G/zDZjvqudFGZQZ/caU0UWaDFme0IlG5iW2fFXtVwIWimnJq5i398+aMDFs9G6
+EcppyfMjOrzcjF/l9KMxOWW4YJ9YVf80YQ1dqYGoKGREsea4Ic17HFGn2zYXVLXS
+EQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/hosts/carol/etc/swanctl/pubkey/moonPub.pem b/testing/tests/swanctl/rw-pubkey-keyid/hosts/carol/etc/swanctl/pubkey/moonPub.pem
new file mode 100644
index 0000000..94fadce
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/hosts/carol/etc/swanctl/pubkey/moonPub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApHwF+sUXQdH+WwYzdPMz
+pjuwhGGvHgsmBah1IQsPsddL9gZygerzpTM1vvQ4kbRuvE3SZWLf9uKEbiQV9IAB
+r87L9JAva56EHIAiUMuG8WizVbIKIhQlZc8S2mIwAW0Jc6EmnoJv9j6F/tVD9+6x
+vMJbwHLi0h7BUO9tBVLPy72YeGNBY6Cob4CrOuFOJyACezJ7i9vZ+XzOfnXpu7qL
+0DgYP/n2maPEJGEivTFunkJD/mJ8DecyLTQcchsCj2118BMuf2qjVn4UWPCBBuhy
+YK5wsATB1ANeAtlFfgH+wsuHjZwtTJru05lGHBZ3F2hZ9PO68hVHbIZZj6SB8X47
+nwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/hosts/carol/etc/swanctl/rsa/carolKey.pem b/testing/tests/swanctl/rw-pubkey-keyid/hosts/carol/etc/swanctl/rsa/carolKey.pem
new file mode 100644
index 0000000..1454ec5
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/hosts/carol/etc/swanctl/rsa/carolKey.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,7E1D40A7901772BA4D22AF58AA2DC76F
+
+1jt4EsxtHvgpSLN8PA/kSVKgoAsBEBQb8RK6VGnZywMCnpJdLKdPisGGYKNPg53b
+/0AFBmQVE60M8icbSAIUrAtyKxaBkoc9A7ibNCjobi0UzXTm3GcZZ1EC4/lE9PQZ
+/2FbcPgQWN3kZraZDkeP9XBXl6PorES8xvQUxJ9pd4hL7/c28fIApGhEimkIZO8o
+Qb7bR2cNCLYQAR6PeDoqhV39gvWoh77wp1WB3tQVbkS6MI/xl3wY2QVdq3Sbszh+
+f6lDU/SZS8BU0f44FRoInPp0GasgJ7MCiuEIshjuNPa50QkMcnNJsSgVEuw2hjN6
+LvAXx7vPt9pKpQfnu7YSJUsXDYN6PyXt7sZ8hDqraYIcI6eMpEBaTpItPSV2eckv
+06KC24Oa66E1yufNFAY49S2OY+pJA0W5zmcCqCjdrfJ+wNQYKZpbrfGz4VRzlFJC
+e3VkmAFwA5rcZdlp/mU2XREy+TaWsHMnpL0NcMHGmsfkTgaJIkRWalrdxlNTeitr
+3boNHWk0ESyMcBYRpM3eNXsGpiYy93u0bhrPbnqJsV6miKqpbs1aBNjlJ9s1Y2fC
+sko5/v7uMjb5tLF3lWQZfTu+bYtpGxFrqHJjhd8yd4gL1cFi30JcjczhwRY3Dily
+c0BFekMGmPc1djn6tfIFu13X9xTxyidCpVaT9UGnOaQs9OF1u8XAnZDaQgPwjLiy
+UlOE8xQ60LrhWLD582FsFnZz56bZ+QOQRWDMsB8nJeqnFXKfcRlnr0qlG6lTfA8h
+XkK/qGpdVvivS+CpbhVP6ixdEfa91Rx4NjLj53LGqOYwFEkM/OAIuMJetBfx3v9T
+iQfv594KE32nv9besnKlmJr2cGQWBYg1pUOtFj/aZ00yuXacv8qwzbrt4xGGDYGO
+Aj5Yf93UEcVkTySO1xJ1yiC6GJv1lLm0i5StwykHypxFijKe/zOpgtHVa5v5igjO
+v6cfhfJGGgIPTYrtt+EDKXcayvy2e2U/3HYVCHYiiMPX8AvP/R6m7MGrzYxm/WyO
+t68EWXSDLfuR3qcIlpP4aSBxuSpKhY/dIkS/beKZ7Njx1s4jSuYDMbKuuCRFSU2H
+8ISHS0kh3FetiS8IyIYzxab+KQZwnVtiGj4oaAhgFTIIoH26Fv5+xka74JdzOSUA
+jR9puKuxaegVWQVBx4cCyg6hAdewRm64PAcbApZWrPvMPBfTZFnXeifmaurcdK8p
+p/1eLrrPnNM6+Fh6lcKdX74yHPz3eWP3K1njZegzWnChhEWElPhJr6qYNQjd+lAS
+7650RJ3CJLUxBffnRR9nTArxFNI5jGWg/plLJTaRT5x5qg1dGNMqntpoeiY++Ttk
+GFDGVIOICBze6SOvzkZBbuXLJSWmWj5g9J2cYsLoOvlwsDT7FzKl8p6VY4V+SQb+
+4PN8qZWmOeczaLEhZ1QLmTKFpz9+wUZsXeBd1s78bWJR0zhraMPa0UJ9GBGq6uQ0
+yZ4Xm5KHKcgoewCUQMekU9ECsmR5NuC7VFDaa1OdPEVnEYR1xtaWUY0lYKOiixnd
++85fSq/yAXI/r0O4ISA55o9y1kDqVibTwJacb6xXGg8dHSH+TtigwD8fK9mekkDC
+-----END RSA PRIVATE KEY-----
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-pubkey-keyid/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..f1a074f
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,34 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = pubkey
+         pubkeys = carolPub.pem
+      }
+      remote {
+         auth = pubkey
+         pubkeys = moonPub.pem 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-ecp256
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-ecp256
+   }
+}
+
+secrets {
+
+   rsa-carol {
+      file = carolKey.pem
+      secret = "nH5ZQEWtku0RJEZ6"
+   }
+}
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/hosts/dave/etc/strongswan.conf b/testing/tests/swanctl/rw-pubkey-keyid/hosts/dave/etc/strongswan.conf
new file mode 100755
index 0000000..dc166b5
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,14 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 pubkey openssl random 
+}
+
+charon {
+  load = random nonce openssl pem pkcs1 pubkey kernel-netlink socket-default updown vici 
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/hosts/dave/etc/swanctl/pubkey/davePub.pem b/testing/tests/swanctl/rw-pubkey-keyid/hosts/dave/etc/swanctl/pubkey/davePub.pem
new file mode 100644
index 0000000..154ac50
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/hosts/dave/etc/swanctl/pubkey/davePub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1jzcTcWEzV+14gWt0dJC
+Ew8ZYpfWCD4lTz0grXvhf+T9gMHx9vx3SiZvAq+CBTuTkpsBydpUEbQC9GZv6qRd
+1FmIQCUk6pHZit+UH44w3tuc+YNB6QjT1PMMm31rULX14jGZQnaHYN4MASfGumnX
+CwqdYF3jwx5iGOQAStGHHwDxmUFuR3IZAkP7Lwa2nSJZLivPxqIZDS9hL4/0NWQw
+ltsaGXZqrBVj4Xffn/8tUbbjj7LNdN/WjxovA+XX48dyBq834zvrpjduojlgeCHY
+IQlMJoF/jOihMFJDpOvVxDkH/9XnX0nXH+6H//YKkRBdsVgWJTeQuZNM/P2lyZ5W
+QwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/hosts/dave/etc/swanctl/pubkey/moonPub.pem b/testing/tests/swanctl/rw-pubkey-keyid/hosts/dave/etc/swanctl/pubkey/moonPub.pem
new file mode 100644
index 0000000..94fadce
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/hosts/dave/etc/swanctl/pubkey/moonPub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApHwF+sUXQdH+WwYzdPMz
+pjuwhGGvHgsmBah1IQsPsddL9gZygerzpTM1vvQ4kbRuvE3SZWLf9uKEbiQV9IAB
+r87L9JAva56EHIAiUMuG8WizVbIKIhQlZc8S2mIwAW0Jc6EmnoJv9j6F/tVD9+6x
+vMJbwHLi0h7BUO9tBVLPy72YeGNBY6Cob4CrOuFOJyACezJ7i9vZ+XzOfnXpu7qL
+0DgYP/n2maPEJGEivTFunkJD/mJ8DecyLTQcchsCj2118BMuf2qjVn4UWPCBBuhy
+YK5wsATB1ANeAtlFfgH+wsuHjZwtTJru05lGHBZ3F2hZ9PO68hVHbIZZj6SB8X47
+nwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-pubkey-keyid/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..4383ab8
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,26 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = pubkey
+         pubkeys = davePub.pem
+      }
+      remote {
+         auth = pubkey
+         pubkeys = moonPub.pem
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-ecp256
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-ecp256
+   }
+}
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/strongswan.conf b/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/strongswan.conf
new file mode 100755
index 0000000..720e903
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,14 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 x509 revocation constraints pubkey openssl random 
+}
+
+charon {
+  load = random nonce openssl pem pkcs1 pubkey kernel-netlink socket-default updown vici 
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/swanctl/pubkey/carolPub.pem b/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/swanctl/pubkey/carolPub.pem
new file mode 100644
index 0000000..8fdc45a
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/swanctl/pubkey/carolPub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt/PUNxfK3+w4AuLUhn9F
+y49rmb7h+JJJPbBVZauXDeFSN6LAt+Cguu0poZfiL4C3zZmiXaZ1sRcWk772rFeW
+I/a7R97Go/iYG5m6zcQsDzYQ4vSVDZqECLw7epp+QMwFKC+h4mkTA17TRSCHneDu
+FPt3Dy1KBw8apCRa60ggpP1Pp78dsc2NG1iXD1mUeynyBJiOD9Dq9Xqh+2254xQP
+01G/zDZjvqudFGZQZ/caU0UWaDFme0IlG5iW2fFXtVwIWimnJq5i398+aMDFs9G6
+EcppyfMjOrzcjF/l9KMxOWW4YJ9YVf80YQ1dqYGoKGREsea4Ic17HFGn2zYXVLXS
+EQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/swanctl/pubkey/davePub.pem b/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/swanctl/pubkey/davePub.pem
new file mode 100644
index 0000000..154ac50
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/swanctl/pubkey/davePub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1jzcTcWEzV+14gWt0dJC
+Ew8ZYpfWCD4lTz0grXvhf+T9gMHx9vx3SiZvAq+CBTuTkpsBydpUEbQC9GZv6qRd
+1FmIQCUk6pHZit+UH44w3tuc+YNB6QjT1PMMm31rULX14jGZQnaHYN4MASfGumnX
+CwqdYF3jwx5iGOQAStGHHwDxmUFuR3IZAkP7Lwa2nSJZLivPxqIZDS9hL4/0NWQw
+ltsaGXZqrBVj4Xffn/8tUbbjj7LNdN/WjxovA+XX48dyBq834zvrpjduojlgeCHY
+IQlMJoF/jOihMFJDpOvVxDkH/9XnX0nXH+6H//YKkRBdsVgWJTeQuZNM/P2lyZ5W
+QwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/swanctl/pubkey/moonPub.pem b/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/swanctl/pubkey/moonPub.pem
new file mode 100644
index 0000000..94fadce
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/swanctl/pubkey/moonPub.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApHwF+sUXQdH+WwYzdPMz
+pjuwhGGvHgsmBah1IQsPsddL9gZygerzpTM1vvQ4kbRuvE3SZWLf9uKEbiQV9IAB
+r87L9JAva56EHIAiUMuG8WizVbIKIhQlZc8S2mIwAW0Jc6EmnoJv9j6F/tVD9+6x
+vMJbwHLi0h7BUO9tBVLPy72YeGNBY6Cob4CrOuFOJyACezJ7i9vZ+XzOfnXpu7qL
+0DgYP/n2maPEJGEivTFunkJD/mJ8DecyLTQcchsCj2118BMuf2qjVn4UWPCBBuhy
+YK5wsATB1ANeAtlFfgH+wsuHjZwtTJru05lGHBZ3F2hZ9PO68hVHbIZZj6SB8X47
+nwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..eac4bc1
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,20 @@
+connections {
+
+   rw-carol {
+      include swanctl_base.conf
+
+      remote {
+         auth = pubkey
+         pubkeys = carolPub.pem
+      }
+   }
+
+   rw-dave {
+      include swanctl_base.conf
+
+      remote {
+         auth = pubkey
+         pubkeys = davePub.pem
+      }
+   }
+}
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/swanctl/swanctl_base.conf b/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/swanctl/swanctl_base.conf
new file mode 100755
index 0000000..61e71f8
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/hosts/moon/etc/swanctl/swanctl_base.conf
@@ -0,0 +1,16 @@
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey
+         pubkeys = moonPub.pem
+      }
+      children {
+         net {
+            local_ts  = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-ecp256
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-ecp256
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/posttest.dat b/testing/tests/swanctl/rw-pubkey-keyid/posttest.dat
new file mode 100755
index 0000000..48a4abe
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/posttest.dat
@@ -0,0 +1,11 @@
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
+moon::rm /etc/swanctl/pubkey/*
+carol::rm /etc/swanctl/pubkey/*
+dave::rm /etc/swanctl/pubkey/*
+moon::iptables-restore < /etc/iptables.flush
+carol::iptables-restore < /etc/iptables.flush
+dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/pretest.dat b/testing/tests/swanctl/rw-pubkey-keyid/pretest.dat
new file mode 100755
index 0000000..de43d51
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/pretest.dat
@@ -0,0 +1,15 @@
+moon::iptables-restore < /etc/iptables.rules
+carol::iptables-restore < /etc/iptables.rules
+dave::iptables-restore < /etc/iptables.rules
+moon::cd /etc/swanctl; rm x509/* x509ca/*
+carol::cd /etc/swanctl; rm x509/* x509ca/*
+dave::cd /etc/swanctl; rm x509/* x509ca/*
+moon::cat /etc/swanctl/swanctl_base.conf
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw-carol
+carol::expect-connection home
+carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/rw-pubkey-keyid/test.conf b/testing/tests/swanctl/rw-pubkey-keyid/test.conf
new file mode 100755
index 0000000..1227b9d
--- /dev/null
+++ b/testing/tests/swanctl/rw-pubkey-keyid/test.conf
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# guest instances used for this test
+
+# All guest instances that are required for this test
+#
+VIRTHOSTS="alice moon carol winnetou dave"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-m-c-w-d.png"
+
+# Guest instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="moon"
+
+# Guest instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon carol dave"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/swanctl/shunt-policies-nat-rw/description.txt b/testing/tests/swanctl/shunt-policies-nat-rw/description.txt
new file mode 100644
index 0000000..b95669d
--- /dev/null
+++ b/testing/tests/swanctl/shunt-policies-nat-rw/description.txt
@@ -0,0 +1,7 @@
+The roadwarriors <b>alice</b> and <b>venus</b> sitting behind the NAT router <b>moon</b> set up
+tunnels to gateway <b>sun</b>. They tunnel all traffic to the gateway.  In order to prevent
+local traffic within the <b>10.1.0.0/16</b> subnet to enter the tunnel, both set up a <b>local-net</b>
+shunt policy with <b>mode = pass</b>.
+<p/>
+In order to test the tunnel, the NAT-ed hosts <b>alice</b> and <b>venus</b>
+ping each other and the client <b>bob</b> behind the gateway <b>sun</b>.
diff --git a/testing/tests/swanctl/shunt-policies-nat-rw/evaltest.dat b/testing/tests/swanctl/shunt-policies-nat-rw/evaltest.dat
new file mode 100644
index 0000000..d89eeb6
--- /dev/null
+++ b/testing/tests/swanctl/shunt-policies-nat-rw/evaltest.dat
@@ -0,0 +1,14 @@
+alice::swanctl --list-pols --raw 2> /dev/null::local-net.*mode=PASS local-ts=\[10.1.0.0/16] remote-ts=\[10.1.0.0/16::YES
+venus::swanctl --list-pols --raw 2> /dev/null::local-net.*mode=PASS local-ts=\[10.1.0.0/16] remote-ts=\[10.1.0.0/16::YES
+alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
+alice::ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
+venus::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
+venus::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+alice::swanctl --list-sas --raw 2> /dev/null::nat-t.*version=2 state=ESTABLISHED local-host=10.1.0.10 local-port=4500 local-id=alice at strongswan.org remote-host=192.168.0.2 remote-port=4500 remote-id=sun.strongswan.org initiator=yes.*nat-local=yes nat-any=yes encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.3.0.1] child-sas.*nat-t.*state=INSTALLED mode=TUNNEL protocol=ESP encap=yes.*encr-alg=AES_GCM_16 encr-keysize [...]
+venus::swanctl --list-sas --raw 2> /dev/null::nat-t.*version=2 state=ESTABLISHED local-host=10.1.0.20 local-port=4500 local-id=venus.strongswan.org remote-host=192.168.0.2 remote-port=4500 remote-id=sun.strongswan.org initiator=yes.*nat-local=yes nat-any=yes encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*local-vips=\[10.3.0.2] child-sas.*nat-t.*state=INSTALLED mode=TUNNEL protocol=ESP encap=yes.*encr-alg=AES_GCM_16 encr-keysize [...]
+sun::swanctl --list-sas --ike-id 1 --raw 2> /dev/null::nat-t.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=4500 local-id=sun.strongswan.org remote-host=192.168.0.1.*remote-id=alice at strongswan.org.*nat-remote=yes nat-any=yes encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.3.0.1] child-sas.*nat-t.*state=INSTALLED mode=TUNNEL protocol=ESP encap=yes.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[ [...]
+sun::swanctl --list-sas --ike-id 2 --raw 2> /dev/null::nat-t.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=4500 local-id=sun.strongswan.org remote-host=192.168.0.1.*remote-id=venus.strongswan.org.*nat-remote=yes nat-any=yes encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*remote-vips=\[10.3.0.2] child-sas.*nat-t.*state=INSTALLED mode=TUNNEL protocol=ESP encap=yes.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[ [...]
+moon::tcpdump::IP moon.strongswan.org.* > sun.strongswan.org.4500: UDP-encap: ESP::YES
+moon::tcpdump::IP sun.strongswan.org.4500 > moon.strongswan.org.*: UDP-encap: ESP::YES
+alice::tcpdump::IP alice.strongswan.org > venus.strongswan.org: ICMP::YES
+alice::tcpdump::IP venus.strongswan.org > alice.strongswan.org: ICMP::YES
diff --git a/testing/tests/swanctl/shunt-policies-nat-rw/hosts/alice/etc/strongswan.conf b/testing/tests/swanctl/shunt-policies-nat-rw/hosts/alice/etc/strongswan.conf
new file mode 100644
index 0000000..9622bb0
--- /dev/null
+++ b/testing/tests/swanctl/shunt-policies-nat-rw/hosts/alice/etc/strongswan.conf
@@ -0,0 +1,11 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+  keep_alive = 5
+}
diff --git a/testing/tests/swanctl/shunt-policies-nat-rw/hosts/alice/etc/swanctl/swanctl.conf b/testing/tests/swanctl/shunt-policies-nat-rw/hosts/alice/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..373f8a7
--- /dev/null
+++ b/testing/tests/swanctl/shunt-policies-nat-rw/hosts/alice/etc/swanctl/swanctl.conf
@@ -0,0 +1,40 @@
+connections {
+
+   nat-t {
+      remote_addrs = 192.168.0.2 
+      vips = 0.0.0.0
+
+      local {
+         auth = pubkey
+         certs = aliceCert.pem
+         id = alice at strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = sun.strongswan.org 
+      }
+      children {
+         nat-t {
+            remote_ts = 0.0.0.0/0 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+
+   local-net {
+
+      children {
+         local-net {
+            local_ts  = 10.1.0.0/16
+            remote_ts = 10.1.0.0/16
+
+            mode = pass
+            start_action = trap
+         }
+      }
+   }
+}
diff --git a/testing/tests/swanctl/shunt-policies-nat-rw/hosts/sun/etc/iptables.rules b/testing/tests/swanctl/shunt-policies-nat-rw/hosts/sun/etc/iptables.rules
new file mode 100644
index 0000000..ae8f9a6
--- /dev/null
+++ b/testing/tests/swanctl/shunt-policies-nat-rw/hosts/sun/etc/iptables.rules
@@ -0,0 +1,24 @@
+*filter
+
+# default policy is DROP
+-P INPUT DROP
+-P OUTPUT DROP
+-P FORWARD DROP
+
+# allow IKE
+-A INPUT  -i eth0 -p udp --dport 500 -j ACCEPT
+-A OUTPUT -o eth0 -p udp --sport 500 -j ACCEPT
+
+# allow MobIKE
+-A INPUT  -i eth0 -p udp --dport 4500 -j ACCEPT
+-A OUTPUT -o eth0 -p udp --sport 4500 -j ACCEPT
+
+# allow ssh
+-A INPUT  -p tcp --dport 22 -j ACCEPT
+-A OUTPUT -p tcp --sport 22 -j ACCEPT
+
+# allow crl fetch from winnetou
+-A INPUT  -i eth0 -p tcp --sport 80 -s PH_IP_WINNETOU -j ACCEPT
+-A OUTPUT -o eth0 -p tcp --dport 80 -d PH_IP_WINNETOU -j ACCEPT
+
+COMMIT
diff --git a/testing/tests/swanctl/shunt-policies-nat-rw/hosts/sun/etc/strongswan.conf b/testing/tests/swanctl/shunt-policies-nat-rw/hosts/sun/etc/strongswan.conf
new file mode 100644
index 0000000..38794af
--- /dev/null
+++ b/testing/tests/swanctl/shunt-policies-nat-rw/hosts/sun/etc/strongswan.conf
@@ -0,0 +1,11 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    pools = /usr/local/sbin/swanctl --load-pools
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/shunt-policies-nat-rw/hosts/sun/etc/swanctl/swanctl.conf b/testing/tests/swanctl/shunt-policies-nat-rw/hosts/sun/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..2f21d4a
--- /dev/null
+++ b/testing/tests/swanctl/shunt-policies-nat-rw/hosts/sun/etc/swanctl/swanctl.conf
@@ -0,0 +1,32 @@
+connections {
+
+   nat-t {
+      local_addrs  = 192.168.0.2
+      pools = rw_pool
+
+      local {
+         auth = pubkey
+         certs = sunCert.pem
+         id = sun.strongswan.org
+      }
+      remote {
+         auth = pubkey
+      }
+      children {
+         nat-t {
+            local_ts  = 0.0.0.0/0
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+pools {
+   rw_pool {
+      addrs = 10.3.0.0/28
+   }
+}
diff --git a/testing/tests/swanctl/shunt-policies-nat-rw/hosts/venus/etc/strongswan.conf b/testing/tests/swanctl/shunt-policies-nat-rw/hosts/venus/etc/strongswan.conf
new file mode 100644
index 0000000..9622bb0
--- /dev/null
+++ b/testing/tests/swanctl/shunt-policies-nat-rw/hosts/venus/etc/strongswan.conf
@@ -0,0 +1,11 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce aes sha1 sha2 pem pkcs1 gmp x509 curl revocation hmac vici kernel-netlink socket-default updown
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+  keep_alive = 5
+}
diff --git a/testing/tests/swanctl/shunt-policies-nat-rw/hosts/venus/etc/swanctl/swanctl.conf b/testing/tests/swanctl/shunt-policies-nat-rw/hosts/venus/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..bb9ca08
--- /dev/null
+++ b/testing/tests/swanctl/shunt-policies-nat-rw/hosts/venus/etc/swanctl/swanctl.conf
@@ -0,0 +1,40 @@
+connections {
+
+   nat-t {
+      remote_addrs = 192.168.0.2 
+      vips = 0.0.0.0
+
+      local {
+         auth = pubkey
+         certs = venusCert.pem
+         id = venus.strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = sun.strongswan.org 
+      }
+      children {
+         nat-t {
+            remote_ts = 0.0.0.0/0 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+
+   local-net {
+
+      children {
+         local-net {
+            local_ts  = 10.1.0.0/16
+            remote_ts = 10.1.0.0/16
+
+            mode = pass
+            start_action = trap
+         }
+      }
+   }
+}
diff --git a/testing/tests/swanctl/shunt-policies-nat-rw/posttest.dat b/testing/tests/swanctl/shunt-policies-nat-rw/posttest.dat
new file mode 100644
index 0000000..b02b193
--- /dev/null
+++ b/testing/tests/swanctl/shunt-policies-nat-rw/posttest.dat
@@ -0,0 +1,5 @@
+alice::service charon stop 2> /dev/null
+venus::service charon stop 2> /dev/null
+sun::service charon stop 2> /dev/null
+sun::iptables-restore < /etc/iptables.flush
+moon::iptables -t nat -F
diff --git a/testing/tests/swanctl/shunt-policies-nat-rw/pretest.dat b/testing/tests/swanctl/shunt-policies-nat-rw/pretest.dat
new file mode 100644
index 0000000..d6bc070
--- /dev/null
+++ b/testing/tests/swanctl/shunt-policies-nat-rw/pretest.dat
@@ -0,0 +1,11 @@
+sun::iptables-restore < /etc/iptables.rules
+moon::iptables -t nat -A POSTROUTING -o eth0 -s 10.1.0.0/16 -p udp -j SNAT --to-source PH_IP_MOON:1024-1100
+moon::iptables -t nat -A POSTROUTING -o eth0 -s 10.1.0.0/16 -p tcp -j SNAT --to-source PH_IP_MOON:2000-2100
+sun::service charon start 2> /dev/null
+alice::service charon start 2> /dev/null
+venus::service charon start 2> /dev/null
+sun::expect-connection nat-t
+alice::expect-connection nat-t
+venus::expect-connection nat-t
+alice::swanctl --initiate --child nat-t 2> /dev/null
+venus::swanctl --initiate --child nat-t 2> /dev/null
diff --git a/testing/tests/swanctl/shunt-policies-nat-rw/test.conf b/testing/tests/swanctl/shunt-policies-nat-rw/test.conf
new file mode 100644
index 0000000..34b0ba1
--- /dev/null
+++ b/testing/tests/swanctl/shunt-policies-nat-rw/test.conf
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# guest instances used for this test
+
+# All guest instances that are required for this test
+#
+VIRTHOSTS="alice venus moon winnetou sun bob"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-v-m-w-s-b.png"
+
+# Guest instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="alice moon"
+
+# Guest instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="alice venus sun"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/swanctl/xauth-rsa/description.txt b/testing/tests/swanctl/xauth-rsa/description.txt
new file mode 100644
index 0000000..9e78e41
--- /dev/null
+++ b/testing/tests/swanctl/xauth-rsa/description.txt
@@ -0,0 +1,9 @@
+The roadwarriors <b>carol</b> and <b>dave</b> set up a connection to gateway <b>moon</b>.
+The authentication is based on RSA public key signatures (<b>pubkey</b>) using X.509 certificates
+in the first round followed by extended authentication (<b>xauth</b>) of <b>carol</b> and <b>dave</b>
+based on user names equal to the <b>IKEv1 identity</b> (<b>carol at strongswan.org</b> and
+<b>dave at strongswan.org</b>, respectively) and corresponding <b>XAuth</b> user passwords.
+<p>
+Upon the successful establishment of the IPsec tunnel, automatically inserted iptables-based
+firewall rules let pass the tunneled traffic. In order to test both tunnel and firewall,
+<b>carol</b> and <b>dave</b> ping the client <b>alice</b> behind the gateway <b>moon</b>.
diff --git a/testing/tests/swanctl/xauth-rsa/evaltest.dat b/testing/tests/swanctl/xauth-rsa/evaltest.dat
new file mode 100644
index 0000000..c50c7fb
--- /dev/null
+++ b/testing/tests/swanctl/xauth-rsa/evaltest.dat
@@ -0,0 +1,12 @@
+moon:: cat /var/log/daemon.log::XAuth authentication of.*carol at strongswan.org.*successful::YES
+moon:: cat /var/log/daemon.log::XAuth authentication of.*dave at strongswan.org.*successful::YES
+carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=1 state=ESTABLISHED local-host=192.168.0.100 local-port=500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072 established=1.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128 dh-group=MODP_3072.*local-ts=\[192.168. [...]
+dave::swanctl --list-sas --raw 2> /dev/null::home.*version=1 state=ESTABLISHED local-host=192.168.0.200 local-port=500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128 dh-group=MODP_3072.*local-ts=\[192.168.0.200/32] remote [...]
+moon::swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=1 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128 dh-group=MODP_3072.*local-ts=\[10.1.0.0/16] remote-ts=\[192. [...]
+moon::swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=1 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128 dh-group=MODP_3072.*local-ts=\[10.1.0.0/16] remote-ts=\[192.1 [...]
+moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
+moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
+moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
+moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES
diff --git a/testing/tests/swanctl/xauth-rsa/hosts/carol/etc/strongswan.conf b/testing/tests/swanctl/xauth-rsa/hosts/carol/etc/strongswan.conf
new file mode 100644
index 0000000..2976558
--- /dev/null
+++ b/testing/tests/swanctl/xauth-rsa/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,10 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce sha1 sha2 aes hmac pem pkcs1 x509 revocation gmp curl xauth-generic kernel-netlink socket-default updown vici
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/xauth-rsa/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/swanctl/xauth-rsa/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..2d2639e
--- /dev/null
+++ b/testing/tests/swanctl/xauth-rsa/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,38 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = pubkey
+         certs = carolCert.pem
+         id = carol at strongswan.org
+      }
+      local-xauth {
+         auth = xauth
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 1 
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   xauth-carol {
+      id = carol at strongswan.org
+      secret = "4iChxLT3" 
+   }
+}
diff --git a/testing/tests/swanctl/xauth-rsa/hosts/dave/etc/strongswan.conf b/testing/tests/swanctl/xauth-rsa/hosts/dave/etc/strongswan.conf
new file mode 100644
index 0000000..2976558
--- /dev/null
+++ b/testing/tests/swanctl/xauth-rsa/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,10 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce sha1 sha2 aes hmac pem pkcs1 x509 revocation gmp curl xauth-generic kernel-netlink socket-default updown vici
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/xauth-rsa/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/swanctl/xauth-rsa/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..f3758e3
--- /dev/null
+++ b/testing/tests/swanctl/xauth-rsa/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,38 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = pubkey
+         certs = daveCert.pem
+         id = dave at strongswan.org
+      }
+      local-xauth {
+         auth = xauth
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 1 
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   xauth-dave {
+      id = dave at strongswan.org
+      secret = "ryftzG4A"
+   }
+}
diff --git a/testing/tests/swanctl/xauth-rsa/hosts/moon/etc/strongswan.conf b/testing/tests/swanctl/xauth-rsa/hosts/moon/etc/strongswan.conf
new file mode 100644
index 0000000..2976558
--- /dev/null
+++ b/testing/tests/swanctl/xauth-rsa/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,10 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce sha1 sha2 aes hmac pem pkcs1 x509 revocation gmp curl xauth-generic kernel-netlink socket-default updown vici
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  } 
+}
diff --git a/testing/tests/swanctl/xauth-rsa/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/swanctl/xauth-rsa/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..27a8802
--- /dev/null
+++ b/testing/tests/swanctl/xauth-rsa/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,40 @@
+connections {
+
+   rw {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey
+         certs = moonCert.pem
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = pubkey
+      }
+      remote-xauth {
+         auth = xauth
+      }
+      children {
+         net {
+            local_ts  = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm128-modp3072
+         }
+      }
+      version = 1 
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   xauth-carol {
+      id = carol at strongswan.org
+      secret = "4iChxLT3" 
+   }
+   xauth-dave {
+      id = dave at strongswan.org
+      secret = "ryftzG4A"
+   }
+}
diff --git a/testing/tests/swanctl/xauth-rsa/posttest.dat b/testing/tests/swanctl/xauth-rsa/posttest.dat
new file mode 100644
index 0000000..d7107cc
--- /dev/null
+++ b/testing/tests/swanctl/xauth-rsa/posttest.dat
@@ -0,0 +1,8 @@
+carol::swanctl --terminate --ike home
+dave::swanctl --terminate --ike home
+carol::service charon stop 2> /dev/null
+dave::service charon stop 2> /dev/null
+moon::service charon stop 2> /dev/null
+moon::iptables-restore < /etc/iptables.flush
+carol::iptables-restore < /etc/iptables.flush
+dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/swanctl/xauth-rsa/pretest.dat b/testing/tests/swanctl/xauth-rsa/pretest.dat
new file mode 100644
index 0000000..762c354
--- /dev/null
+++ b/testing/tests/swanctl/xauth-rsa/pretest.dat
@@ -0,0 +1,11 @@
+moon::iptables-restore < /etc/iptables.rules
+carol::iptables-restore < /etc/iptables.rules
+dave::iptables-restore < /etc/iptables.rules
+moon::service charon start 2> /dev/null
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::expect-connection rw
+carol::expect-connection home
+carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/xauth-rsa/test.conf b/testing/tests/swanctl/xauth-rsa/test.conf
new file mode 100644
index 0000000..1227b9d
--- /dev/null
+++ b/testing/tests/swanctl/xauth-rsa/test.conf
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# guest instances used for this test
+
+# All guest instances that are required for this test
+#
+VIRTHOSTS="alice moon carol winnetou dave"
+
+# Corresponding block diagram
+#
+DIAGRAM="a-m-c-w-d.png"
+
+# Guest instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="moon"
+
+# Guest instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon carol dave"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-11-fhh/evaltest.dat b/testing/tests/tnc/tnccs-11-fhh/evaltest.dat
index 3478c07..800fa3c 100644
--- a/testing/tests/tnc/tnccs-11-fhh/evaltest.dat
+++ b/testing/tests/tnc/tnccs-11-fhh/evaltest.dat
@@ -1,19 +1,18 @@
 carol::cat /var/log/daemon.log::TNCCS-Recommendation.*allow::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/28::YES
 dave:: cat /var/log/daemon.log::TNCCS-Recommendation.*isolate::YES
 dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.16/28::YES
 moon:: cat /var/log/daemon.log::added group membership 'allow'::YES
 moon:: cat /var/log/daemon.log::authentication of 'carol at strongswan.org' with EAP successful::YES
 moon:: cat /var/log/daemon.log::added group membership 'isolate'::YES
 moon:: cat /var/log/daemon.log::authentication of 'dave at strongswan.org' with EAP successful::YES
-moon:: ipsec statusall 2> /dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.100/32::YES
-moon:: ipsec statusall 2> /dev/null::rw-isolate.*10.1.0.16/28 === 192.168.0.200/32::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.16/ [...]
+moon:: swanctl --list-sas --ike-id 1 --raw  2> /dev/null::rw-allow.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-allow.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/28] remote-ts=\[192.168. [...]
+moon:: swanctl --list-sas --ike-id 2 --raw  2> /dev/null::rw-isolate.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-isolate.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.16/28] remote-ts=\[192. [...]
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_ALICE: icmp_req=1::NO
+carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
 dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
-dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_VENUS: icmp_req=1::NO
-
+dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
diff --git a/testing/tests/tnc/tnccs-11-fhh/hosts/carol/etc/init.d/charon b/testing/tests/tnc/tnccs-11-fhh/hosts/carol/etc/init.d/charon
new file mode 100755
index 0000000..bf3a689
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11-fhh/hosts/carol/etc/init.d/charon
@@ -0,0 +1,158 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          charon 
+# Required-Start:    $remote_fs $syslog
+# Required-Stop:     $remote_fs $syslog
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: strongSwan charon IKE daemon 
+# Description:       with swanctl the strongSwan charon daemon must be
+#                    running in the background
+### END INIT INFO
+
+# Author: Andreas Steffen <andreas.steffen at strongswa.org>
+#
+# Do NOT "set -e"
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin
+DESC="strongSwan charon IKE daemon"
+NAME=charon
+DAEMON=/usr/local/libexec/ipsec/$NAME
+DAEMON_ARGS=""
+PIDFILE=/var/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/charon
+
+export LOG4CXX_CONFIGURATION=/etc/tnc/log4cxx.properties
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcS variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
+# and status_of_proc is working.
+. /lib/lsb/init-functions
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+	# Return
+	#   0 if daemon has been started
+	#   1 if daemon was already running
+	#   2 if daemon could not be started
+	start-stop-daemon --start --quiet --background --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
+		|| return 1
+	start-stop-daemon --start --quiet --background --pidfile $PIDFILE --exec $DAEMON -- \
+		$DAEMON_ARGS \
+		|| return 2
+	# Add code here, if necessary, that waits for the process to be ready
+	# to handle requests from services started subsequently which depend
+	# on this one.  As a last resort, sleep for some time.
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+	# Return
+	#   0 if daemon has been stopped
+	#   1 if daemon was already stopped
+	#   2 if daemon could not be stopped
+	#   other if a failure occurred
+	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
+	RETVAL="$?"
+	[ "$RETVAL" = 2 ] && return 2
+	# Wait for children to finish too if this is a daemon that forks
+	# and if the daemon is only ever run from this initscript.
+	# If the above conditions are not satisfied then add some other code
+	# that waits for the process to drop all resources that could be
+	# needed by services started subsequently.  A last resort is to
+	# sleep for some time.
+	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
+	[ "$?" = 2 ] && return 2
+	# Many daemons don't delete their pidfiles when they exit.
+	rm -f $PIDFILE
+	return "$RETVAL"
+}
+
+#
+# Function that sends a SIGHUP to the daemon/service
+#
+do_reload() {
+	#
+	# If the daemon can reload its configuration without
+	# restarting (for example, when it is sent a SIGHUP),
+	# then implement that here.
+	#
+	start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
+	return 0
+}
+
+case "$1" in
+  start)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+	do_start
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  stop)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+	do_stop
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  status)
+	status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
+	;;
+  #reload|force-reload)
+	#
+	# If do_reload() is not implemented then leave this commented out
+	# and leave 'force-reload' as an alias for 'restart'.
+	#
+	#log_daemon_msg "Reloading $DESC" "$NAME"
+	#do_reload
+	#log_end_msg $?
+	#;;
+  restart|force-reload)
+	#
+	# If the "reload" option is implemented then remove the
+	# 'force-reload' alias
+	#
+	log_daemon_msg "Restarting $DESC" "$NAME"
+	do_stop
+	case "$?" in
+	  0|1)
+		do_start
+		case "$?" in
+			0) log_end_msg 0 ;;
+			1) log_end_msg 1 ;; # Old process is still running
+			*) log_end_msg 1 ;; # Failed to start
+		esac
+		;;
+	  *)
+		# Failed to stop
+		log_end_msg 1
+		;;
+	esac
+	;;
+  *)
+	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+	echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
+	exit 3
+	;;
+esac
+
+:
diff --git a/testing/tests/tnc/tnccs-11-fhh/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-11-fhh/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index caa5bc1..0000000
--- a/testing/tests/tnc/tnccs-11-fhh/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-11-fhh/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11-fhh/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 74942af..0000000
--- a/testing/tests/tnc/tnccs-11-fhh/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol at strongswan.org : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-11-fhh/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-fhh/hosts/carol/etc/strongswan.conf
index d891a2c..063bb6f 100644
--- a/testing/tests/tnc/tnccs-11-fhh/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11-fhh/hosts/carol/etc/strongswan.conf
@@ -1,13 +1,29 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
 
   multiple_authentication=no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+    }
+  }
   plugins {
     eap-tnc {
       protocol = tnccs-1.1
     }
   }
 }
+
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
diff --git a/testing/tests/tnc/tnccs-11-fhh/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-11-fhh/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..0f266dd
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11-fhh/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-11-fhh/hosts/dave/etc/init.d/charon b/testing/tests/tnc/tnccs-11-fhh/hosts/dave/etc/init.d/charon
new file mode 100755
index 0000000..bf3a689
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11-fhh/hosts/dave/etc/init.d/charon
@@ -0,0 +1,158 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          charon 
+# Required-Start:    $remote_fs $syslog
+# Required-Stop:     $remote_fs $syslog
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: strongSwan charon IKE daemon 
+# Description:       with swanctl the strongSwan charon daemon must be
+#                    running in the background
+### END INIT INFO
+
+# Author: Andreas Steffen <andreas.steffen at strongswa.org>
+#
+# Do NOT "set -e"
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin
+DESC="strongSwan charon IKE daemon"
+NAME=charon
+DAEMON=/usr/local/libexec/ipsec/$NAME
+DAEMON_ARGS=""
+PIDFILE=/var/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/charon
+
+export LOG4CXX_CONFIGURATION=/etc/tnc/log4cxx.properties
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcS variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
+# and status_of_proc is working.
+. /lib/lsb/init-functions
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+	# Return
+	#   0 if daemon has been started
+	#   1 if daemon was already running
+	#   2 if daemon could not be started
+	start-stop-daemon --start --quiet --background --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
+		|| return 1
+	start-stop-daemon --start --quiet --background --pidfile $PIDFILE --exec $DAEMON -- \
+		$DAEMON_ARGS \
+		|| return 2
+	# Add code here, if necessary, that waits for the process to be ready
+	# to handle requests from services started subsequently which depend
+	# on this one.  As a last resort, sleep for some time.
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+	# Return
+	#   0 if daemon has been stopped
+	#   1 if daemon was already stopped
+	#   2 if daemon could not be stopped
+	#   other if a failure occurred
+	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
+	RETVAL="$?"
+	[ "$RETVAL" = 2 ] && return 2
+	# Wait for children to finish too if this is a daemon that forks
+	# and if the daemon is only ever run from this initscript.
+	# If the above conditions are not satisfied then add some other code
+	# that waits for the process to drop all resources that could be
+	# needed by services started subsequently.  A last resort is to
+	# sleep for some time.
+	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
+	[ "$?" = 2 ] && return 2
+	# Many daemons don't delete their pidfiles when they exit.
+	rm -f $PIDFILE
+	return "$RETVAL"
+}
+
+#
+# Function that sends a SIGHUP to the daemon/service
+#
+do_reload() {
+	#
+	# If the daemon can reload its configuration without
+	# restarting (for example, when it is sent a SIGHUP),
+	# then implement that here.
+	#
+	start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
+	return 0
+}
+
+case "$1" in
+  start)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+	do_start
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  stop)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+	do_stop
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  status)
+	status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
+	;;
+  #reload|force-reload)
+	#
+	# If do_reload() is not implemented then leave this commented out
+	# and leave 'force-reload' as an alias for 'restart'.
+	#
+	#log_daemon_msg "Reloading $DESC" "$NAME"
+	#do_reload
+	#log_end_msg $?
+	#;;
+  restart|force-reload)
+	#
+	# If the "reload" option is implemented then remove the
+	# 'force-reload' alias
+	#
+	log_daemon_msg "Restarting $DESC" "$NAME"
+	do_stop
+	case "$?" in
+	  0|1)
+		do_start
+		case "$?" in
+			0) log_end_msg 0 ;;
+			1) log_end_msg 1 ;; # Old process is still running
+			*) log_end_msg 1 ;; # Failed to start
+		esac
+		;;
+	  *)
+		# Failed to stop
+		log_end_msg 1
+		;;
+	esac
+	;;
+  *)
+	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+	echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
+	exit 3
+	;;
+esac
+
+:
diff --git a/testing/tests/tnc/tnccs-11-fhh/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-11-fhh/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index ba149c4..0000000
--- a/testing/tests/tnc/tnccs-11-fhh/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftid=dave at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-11-fhh/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11-fhh/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index 5496df7..0000000
--- a/testing/tests/tnc/tnccs-11-fhh/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-dave at strongswan.org : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-11-fhh/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-fhh/hosts/dave/etc/strongswan.conf
index d891a2c..063bb6f 100644
--- a/testing/tests/tnc/tnccs-11-fhh/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11-fhh/hosts/dave/etc/strongswan.conf
@@ -1,13 +1,29 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
 
   multiple_authentication=no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+    }
+  }
   plugins {
     eap-tnc {
       protocol = tnccs-1.1
     }
   }
 }
+
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
diff --git a/testing/tests/tnc/tnccs-11-fhh/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-11-fhh/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..989ab88
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11-fhh/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-11-fhh/hosts/moon/etc/init.d/charon b/testing/tests/tnc/tnccs-11-fhh/hosts/moon/etc/init.d/charon
new file mode 100755
index 0000000..bf3a689
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11-fhh/hosts/moon/etc/init.d/charon
@@ -0,0 +1,158 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          charon 
+# Required-Start:    $remote_fs $syslog
+# Required-Stop:     $remote_fs $syslog
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: strongSwan charon IKE daemon 
+# Description:       with swanctl the strongSwan charon daemon must be
+#                    running in the background
+### END INIT INFO
+
+# Author: Andreas Steffen <andreas.steffen at strongswa.org>
+#
+# Do NOT "set -e"
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin
+DESC="strongSwan charon IKE daemon"
+NAME=charon
+DAEMON=/usr/local/libexec/ipsec/$NAME
+DAEMON_ARGS=""
+PIDFILE=/var/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/charon
+
+export LOG4CXX_CONFIGURATION=/etc/tnc/log4cxx.properties
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcS variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
+# and status_of_proc is working.
+. /lib/lsb/init-functions
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+	# Return
+	#   0 if daemon has been started
+	#   1 if daemon was already running
+	#   2 if daemon could not be started
+	start-stop-daemon --start --quiet --background --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
+		|| return 1
+	start-stop-daemon --start --quiet --background --pidfile $PIDFILE --exec $DAEMON -- \
+		$DAEMON_ARGS \
+		|| return 2
+	# Add code here, if necessary, that waits for the process to be ready
+	# to handle requests from services started subsequently which depend
+	# on this one.  As a last resort, sleep for some time.
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+	# Return
+	#   0 if daemon has been stopped
+	#   1 if daemon was already stopped
+	#   2 if daemon could not be stopped
+	#   other if a failure occurred
+	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
+	RETVAL="$?"
+	[ "$RETVAL" = 2 ] && return 2
+	# Wait for children to finish too if this is a daemon that forks
+	# and if the daemon is only ever run from this initscript.
+	# If the above conditions are not satisfied then add some other code
+	# that waits for the process to drop all resources that could be
+	# needed by services started subsequently.  A last resort is to
+	# sleep for some time.
+	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
+	[ "$?" = 2 ] && return 2
+	# Many daemons don't delete their pidfiles when they exit.
+	rm -f $PIDFILE
+	return "$RETVAL"
+}
+
+#
+# Function that sends a SIGHUP to the daemon/service
+#
+do_reload() {
+	#
+	# If the daemon can reload its configuration without
+	# restarting (for example, when it is sent a SIGHUP),
+	# then implement that here.
+	#
+	start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
+	return 0
+}
+
+case "$1" in
+  start)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+	do_start
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  stop)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+	do_stop
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  status)
+	status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
+	;;
+  #reload|force-reload)
+	#
+	# If do_reload() is not implemented then leave this commented out
+	# and leave 'force-reload' as an alias for 'restart'.
+	#
+	#log_daemon_msg "Reloading $DESC" "$NAME"
+	#do_reload
+	#log_end_msg $?
+	#;;
+  restart|force-reload)
+	#
+	# If the "reload" option is implemented then remove the
+	# 'force-reload' alias
+	#
+	log_daemon_msg "Restarting $DESC" "$NAME"
+	do_stop
+	case "$?" in
+	  0|1)
+		do_start
+		case "$?" in
+			0) log_end_msg 0 ;;
+			1) log_end_msg 1 ;; # Old process is still running
+			*) log_end_msg 1 ;; # Failed to start
+		esac
+		;;
+	  *)
+		# Failed to stop
+		log_end_msg 1
+		;;
+	esac
+	;;
+  *)
+	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+	echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
+	exit 3
+	;;
+esac
+
+:
diff --git a/testing/tests/tnc/tnccs-11-fhh/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-11-fhh/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index 0fdad86..0000000
--- a/testing/tests/tnc/tnccs-11-fhh/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,34 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=eap-ttls
-	leftfirewall=yes
-	rightauth=eap-ttls
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
diff --git a/testing/tests/tnc/tnccs-11-fhh/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11-fhh/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index 2e277cc..0000000
--- a/testing/tests/tnc/tnccs-11-fhh/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
-
-carol at strongswan.org : EAP "Ar3etTnp"
-dave at strongswan.org  : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-11-fhh/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-fhh/hosts/moon/etc/strongswan.conf
index 03f5519..a3d85b0 100644
--- a/testing/tests/tnc/tnccs-11-fhh/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11-fhh/hosts/moon/etc/strongswan.conf
@@ -1,10 +1,22 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-11 tnc-imv updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-11 tnc-imv updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+    }
+  }
   plugins {
     eap-ttls {
       phase2_method = md5
@@ -17,3 +29,7 @@ charon {
     }
   }
 }
+
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
diff --git a/testing/tests/tnc/tnccs-11-fhh/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-11-fhh/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..1238c1a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11-fhh/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,64 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap-carol {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+   eap-dave {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-11-fhh/posttest.dat b/testing/tests/tnc/tnccs-11-fhh/posttest.dat
index 1865a1c..770cf6e 100644
--- a/testing/tests/tnc/tnccs-11-fhh/posttest.dat
+++ b/testing/tests/tnc/tnccs-11-fhh/posttest.dat
@@ -1,6 +1,6 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-11-fhh/pretest.dat b/testing/tests/tnc/tnccs-11-fhh/pretest.dat
index d181aab..f0f6446 100644
--- a/testing/tests/tnc/tnccs-11-fhh/pretest.dat
+++ b/testing/tests/tnc/tnccs-11-fhh/pretest.dat
@@ -6,11 +6,15 @@ carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
 carol::cat /etc/tnc/dummyimc.file
 dave::cat /etc/tnc/dummyimc.file
-moon::LOG4CXX_CONFIGURATION=/etc/tnc/log4cxx.properties ipsec start
-carol::LOG4CXX_CONFIGURATION=/etc/tnc/log4cxx.properties ipsec start
-dave::LOG4CXX_CONFIGURATION=/etc/tnc/log4cxx.properties ipsec start
+carol::rm /etc/swanctl/rsa/*
+dave::rm /etc/swanctl/rsa/*
+carol::rm /etc/swanctl/x509/*
+dave::rm /etc/swanctl/x509/*
+moon::service charon start
+carol::service charon start
+dave::service charon start
 moon::expect-connection rw-allow
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/tnc/tnccs-11-fhh/test.conf b/testing/tests/tnc/tnccs-11-fhh/test.conf
index a8a05af..61f2312 100644
--- a/testing/tests/tnc/tnccs-11-fhh/test.conf
+++ b/testing/tests/tnc/tnccs-11-fhh/test.conf
@@ -23,4 +23,6 @@ IPSECHOSTS="moon carol dave"
 # Guest instances on which FreeRadius is started
 #
 RADIUSHOSTS=
-
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-11-radius-block/evaltest.dat b/testing/tests/tnc/tnccs-11-radius-block/evaltest.dat
index 3f3aa9f..ef02166 100644
--- a/testing/tests/tnc/tnccs-11-radius-block/evaltest.dat
+++ b/testing/tests/tnc/tnccs-11-radius-block/evaltest.dat
@@ -1,14 +1,15 @@
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA.* successful::YES
 carol::cat /var/log/daemon.log::TNCCS-Recommendation.*allow::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
-carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/16::YES
 dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA.* successful::YES
 dave:: cat /var/log/daemon.log::TNCCS-Recommendation.*none::YES
 dave:: cat /var/log/daemon.log::received EAP_FAILURE, EAP authentication failed::YES
-dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.0/16::NO
 moon:: cat /var/log/daemon.log::authentication of 'carol at strongswan.org' with EAP successful::YES
 moon:: cat /var/log/daemon.log::RADIUS authentication of 'dave at strongswan.org' failed::YES
 moon:: cat /var/log/daemon.log::EAP method EAP_TTLS failed for peer dave at strongswan.org::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home::NO
+moon:: swanctl --list-sas --ike-id 1 --raw  2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]::YES
+moon:: swanctl --list-sas --ike-id 2 --raw  2> /dev/null::rw::NO
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_VENUS: icmp_req=1::NO
-
+dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
diff --git a/testing/tests/tnc/tnccs-11-radius-block/hosts/alice/etc/freeradius/sites-available/inner-tunnel-second b/testing/tests/tnc/tnccs-11-radius-block/hosts/alice/etc/freeradius/sites-available/inner-tunnel-second
index 2d49612..c5bde6a 100644
--- a/testing/tests/tnc/tnccs-11-radius-block/hosts/alice/etc/freeradius/sites-available/inner-tunnel-second
+++ b/testing/tests/tnc/tnccs-11-radius-block/hosts/alice/etc/freeradius/sites-available/inner-tunnel-second
@@ -15,6 +15,19 @@ session {
 }
 
 post-auth {
+	if (control:TNC-Status == "Access") {
+		update reply {
+			Tunnel-Type := ESP
+			Filter-Id := "allow"
+		}
+	}
+	elsif (control:TNC-Status == "Isolate") {
+		update reply {
+			Tunnel-Type := ESP
+			Filter-Id := "isolate"
+		}
+	}
+
 	Post-Auth-Type REJECT {
 		attr_filter.access_reject
 	}
diff --git a/testing/tests/tnc/tnccs-11-radius-block/hosts/alice/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-radius-block/hosts/alice/etc/strongswan.conf
index 06c34ed..7622801 100644
--- a/testing/tests/tnc/tnccs-11-radius-block/hosts/alice/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11-radius-block/hosts/alice/etc/strongswan.conf
@@ -1,12 +1,12 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 libimcv {
-  debug_level = 3
+  load = random nonce sha1 sha2 md5 gmp pubkey x509
+  debug_level = 3 
   assessment_result = no
   plugins {
-    imv-scanner {
-      closed_port_policy = no
-      tcp_ports = 80 443
-     }
+    imv-test {
+      rounds = 1 
+    }
   }
 }
diff --git a/testing/tests/tnc/tnccs-11-radius-block/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-11-radius-block/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index e9152e0..0000000
--- a/testing/tests/tnc/tnccs-11-radius-block/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightsubnet=10.1.0.0/16
-	rightauth=pubkey
-	aaa_identity="C=CH, O=Linux strongSwan, CN=aaa.strongswan.org"
-	auto=add
diff --git a/testing/tests/tnc/tnccs-11-radius-block/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11-radius-block/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 74942af..0000000
--- a/testing/tests/tnc/tnccs-11-radius-block/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol at strongswan.org : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-11-radius-block/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-radius-block/hosts/carol/etc/strongswan.conf
index 927c459..80c96b6 100644
--- a/testing/tests/tnc/tnccs-11-radius-block/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11-radius-block/hosts/carol/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
 
   multiple_authentication=no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+    }
+  }
   plugins {
     eap-tnc {
       protocol = tnccs-1.1
diff --git a/testing/tests/tnc/tnccs-11-radius-block/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-11-radius-block/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..ff58c7c
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11-radius-block/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap
+         aaa_id = aaa.strongswan.org
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = pubkey 
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-11-radius-block/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-11-radius-block/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 25589bc..0000000
--- a/testing/tests/tnc/tnccs-11-radius-block/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftid=dave at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightsubnet=10.1.0.0/16
-	rightauth=pubkey
-	aaa_identity="C=CH, O=Linux strongSwan, CN=aaa.strongswan.org"
-	auto=add
diff --git a/testing/tests/tnc/tnccs-11-radius-block/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11-radius-block/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index 5496df7..0000000
--- a/testing/tests/tnc/tnccs-11-radius-block/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-dave at strongswan.org : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-11-radius-block/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-radius-block/hosts/dave/etc/strongswan.conf
index 566457d..691cdbc 100644
--- a/testing/tests/tnc/tnccs-11-radius-block/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11-radius-block/hosts/dave/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
+  load = random nonce aes sha1 sha2 md5 gmp hmac pem pkcs1 x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
 
   multiple_authentication=no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+    }
+  }
   plugins {
     eap-tnc {
       protocol = tnccs-1.1
@@ -14,6 +27,9 @@ charon {
 
 libimcv {
   plugins {
+    imc-test {
+      command = none
+    }
     imc-scanner {
       push_info = no
     }
diff --git a/testing/tests/tnc/tnccs-11-radius-block/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-11-radius-block/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..5af2098
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11-radius-block/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap
+         aaa_id = aaa.strongswan.org
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = pubkey 
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-11-radius-block/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-11-radius-block/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index 98e2525..0000000
--- a/testing/tests/tnc/tnccs-11-radius-block/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftsubnet=10.1.0.0/16
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=pubkey
-	leftfirewall=yes
-	rightauth=eap-radius
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
-	auto=add
diff --git a/testing/tests/tnc/tnccs-11-radius-block/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11-radius-block/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index e86d6aa..0000000
--- a/testing/tests/tnc/tnccs-11-radius-block/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
diff --git a/testing/tests/tnc/tnccs-11-radius-block/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-radius-block/hosts/moon/etc/strongswan.conf
index fbf1617..71fc7dd 100644
--- a/testing/tests/tnc/tnccs-11-radius-block/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11-radius-block/hosts/moon/etc/strongswan.conf
@@ -1,12 +1,19 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-radius updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-radius updown
+
   multiple_authentication=no
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
   plugins {
     eap-radius {
       secret = gv6URkSs 
-      server = PH_IP_ALICE
+      server = 10.1.0.10 
+      filter_id = yes
     }
   }
 }
diff --git a/testing/tests/tnc/tnccs-11-radius-block/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-11-radius-block/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..28b32b7
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11-radius-block/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,27 @@
+connections {
+
+   rw {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey 
+         id = moon.strongswan.org
+         certs = moonCert.pem
+      }
+      remote {
+         auth = eap-radius
+         id = *@strongswan.org
+      }
+      children {
+         rw {
+            local_ts = 10.1.0.0/16
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/tnc/tnccs-11-radius-block/posttest.dat b/testing/tests/tnc/tnccs-11-radius-block/posttest.dat
index 5e5a851..2989f34 100644
--- a/testing/tests/tnc/tnccs-11-radius-block/posttest.dat
+++ b/testing/tests/tnc/tnccs-11-radius-block/posttest.dat
@@ -1,9 +1,8 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
 alice::killall radiusd
 alice::rm /etc/freeradius/sites-enabled/inner-tunnel-second
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
-dave::/etc/init.d/apache2 stop 2> /dev/null
diff --git a/testing/tests/tnc/tnccs-11-radius-block/pretest.dat b/testing/tests/tnc/tnccs-11-radius-block/pretest.dat
index d2bb945..baf8c97 100644
--- a/testing/tests/tnc/tnccs-11-radius-block/pretest.dat
+++ b/testing/tests/tnc/tnccs-11-radius-block/pretest.dat
@@ -1,14 +1,20 @@
 moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
 dave::iptables-restore < /etc/iptables.rules
-dave::/etc/init.d/apache2 start 2> /dev/null
 alice::ln -s /etc/freeradius/sites-available/inner-tunnel-second /etc/freeradius/sites-enabled/inner-tunnel-second
 alice::cat /etc/freeradius/sites-enabled/inner-tunnel-second
 alice::LEAK_DETECTIVE_DISABLE=1 LOG4CXX_CONFIGURATION=/etc/tnc/log4cxx.properties radiusd
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+alice::cat /etc/tnc_config
+carol::cat /etc/tnc_config
+dave::cat /etc/tnc_config
+carol::rm /etc/swanctl/rsa/*
+dave::rm /etc/swanctl/rsa/*
+carol::rm /etc/swanctl/x509/*
+dave::rm /etc/swanctl/x509/*
+moon::service charon start
+carol::service charon start
+dave::service charon start
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home
diff --git a/testing/tests/tnc/tnccs-11-radius-block/test.conf b/testing/tests/tnc/tnccs-11-radius-block/test.conf
index 29bfaa7..8d7f514 100644
--- a/testing/tests/tnc/tnccs-11-radius-block/test.conf
+++ b/testing/tests/tnc/tnccs-11-radius-block/test.conf
@@ -5,11 +5,11 @@
 
 # All guest instances that are required for this test
 #
-VIRTHOSTS="alice moon carol winnetou dave"
+VIRTHOSTS="alice venus moon carol winnetou dave"
 
 # Corresponding block diagram
 #
-DIAGRAM="a-m-c-w-d.png"
+DIAGRAM="a-v-m-c-w-d.png"
 
 # Guest instances on which tcpdump is to be started
 #
@@ -24,3 +24,6 @@ IPSECHOSTS="moon carol dave"
 #
 RADIUSHOSTS="alice"
 
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/evaltest.dat b/testing/tests/tnc/tnccs-11-radius-pts/evaltest.dat
index 955584b..d57b5e7 100644
--- a/testing/tests/tnc/tnccs-11-radius-pts/evaltest.dat
+++ b/testing/tests/tnc/tnccs-11-radius-pts/evaltest.dat
@@ -1,19 +1,18 @@
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA.* successful::YES
 carol::cat /var/log/daemon.log::TNCCS-Recommendation.*allow::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
-carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/28::YES
 dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA.* successful::YES
 dave:: cat /var/log/daemon.log::TNCCS-Recommendation.*isolate::YES
 dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
-dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.16/28::YES
 moon:: cat /var/log/daemon.log::received RADIUS attribute Filter-Id: 'allow'::YES
 moon:: cat /var/log/daemon.log::authentication of 'carol at strongswan.org' with EAP successful::YES
 moon:: cat /var/log/daemon.log::received RADIUS attribute Filter-Id: 'isolate'::YES
 moon:: cat /var/log/daemon.log::authentication of 'dave at strongswan.org' with EAP successful::YES
-moon:: ipsec statusall 2> /dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.100/32::YES
-moon:: ipsec statusall 2> /dev/null::rw-isolate.*10.1.0.16/28 === 192.168.0.200/32::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/28]::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.16/28]::YES
+moon:: swanctl --list-sas --ike-id 1 --raw  2> /dev/null::rw-allow.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*rw-allow.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/28] remote-ts=\[192.168.0. [...]
+moon:: swanctl --list-sas --ike-id 2 --raw  2> /dev/null::rw-isolate.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*rw-isolate.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.16/28] remote-ts=\[192.16 [...]
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_ALICE: icmp_req=1::NO
+carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
 dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
-dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_VENUS: icmp_req=1::NO
-
+dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-11-radius-pts/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index e9152e0..0000000
--- a/testing/tests/tnc/tnccs-11-radius-pts/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightsubnet=10.1.0.0/16
-	rightauth=pubkey
-	aaa_identity="C=CH, O=Linux strongSwan, CN=aaa.strongswan.org"
-	auto=add
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11-radius-pts/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 74942af..0000000
--- a/testing/tests/tnc/tnccs-11-radius-pts/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol at strongswan.org : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-radius-pts/hosts/carol/etc/strongswan.conf
index 3520fd5..978cc66 100644
--- a/testing/tests/tnc/tnccs-11-radius-pts/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11-radius-pts/hosts/carol/etc/strongswan.conf
@@ -1,21 +1,26 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = openssl curl pem pkcs1 random nonce revocation stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
+  load = random nonce openssl pem pkcs1 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
 
   multiple_authentication=no
 
-  plugins {
-    eap-tnc {
-      protocol = tnccs-1.1
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
     }
   }
-}
-
-libimcv {
   plugins {
-    imc-test {
-      command = allow
+    eap-tnc {
+      protocol = tnccs-1.1
     }
   }
 }
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-11-radius-pts/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..1516ad7
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11-radius-pts/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap
+         aaa_id = aaa.strongswan.org
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = pubkey 
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-ecp256
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-ecp256
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-11-radius-pts/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 25589bc..0000000
--- a/testing/tests/tnc/tnccs-11-radius-pts/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftid=dave at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightsubnet=10.1.0.0/16
-	rightauth=pubkey
-	aaa_identity="C=CH, O=Linux strongSwan, CN=aaa.strongswan.org"
-	auto=add
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11-radius-pts/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index 5496df7..0000000
--- a/testing/tests/tnc/tnccs-11-radius-pts/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-dave at strongswan.org : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-radius-pts/hosts/dave/etc/strongswan.conf
index e870608..0bc6e35 100644
--- a/testing/tests/tnc/tnccs-11-radius-pts/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11-radius-pts/hosts/dave/etc/strongswan.conf
@@ -1,26 +1,27 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = openssl curl pem pkcs1 random nonce revocation stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
+  load = random nonce openssl pem pkcs1 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
 
   multiple_authentication=no
-
   retransmit_tries = 5
 
-  plugins {
-    eap-tnc {
-      protocol = tnccs-1.1
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
     }
   }
-}
-
-libimcv {
   plugins {
-    imc-test {
-      command = allow
-    }
-    imc-scanner {
-      push_info = no
+    eap-tnc {
+      protocol = tnccs-1.1
     }
   }
 }
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-11-radius-pts/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..07b35dc
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11-radius-pts/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap
+         aaa_id = aaa.strongswan.org
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = pubkey 
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-ecp256
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-ecp256
+   }
+}
+
+secrets {
+
+   eap {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-11-radius-pts/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index 294964f..0000000
--- a/testing/tests/tnc/tnccs-11-radius-pts/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,33 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=pubkey
-	leftfirewall=yes
-	rightauth=eap-radius
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11-radius-pts/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index e86d6aa..0000000
--- a/testing/tests/tnc/tnccs-11-radius-pts/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-radius-pts/hosts/moon/etc/strongswan.conf
index 6e49677..387236e 100644
--- a/testing/tests/tnc/tnccs-11-radius-pts/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11-radius-pts/hosts/moon/etc/strongswan.conf
@@ -1,12 +1,18 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-radius updown
+  load = random nonce openssl pem pkcs1 x509 revocation curl vici kernel-netlink socket-default eap-radius updown
+
   multiple_authentication=no
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
   plugins {
     eap-radius {
       secret = gv6URkSs 
-      server = PH_IP_ALICE
+      server = 10.1.0.10 
       filter_id = yes
     }
   }
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-11-radius-pts/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..096eb7b
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11-radius-pts/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,53 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey 
+         id = moon.strongswan.org
+         certs = moonCert.pem
+      }
+      remote {
+         auth = eap-radius
+         id = *@strongswan.org
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-ecp256
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-ecp256
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey 
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-radius
+         id = *@strongswan.org
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-ecp256
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-ecp256
+   }
+}
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/posttest.dat b/testing/tests/tnc/tnccs-11-radius-pts/posttest.dat
index 18e0374..db806c3 100644
--- a/testing/tests/tnc/tnccs-11-radius-pts/posttest.dat
+++ b/testing/tests/tnc/tnccs-11-radius-pts/posttest.dat
@@ -1,6 +1,6 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
 alice::killall radiusd
 alice::rm /etc/freeradius/sites-enabled/inner-tunnel-second
 carol::echo 1 > /proc/sys/net/ipv4/ip_forward
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/pretest.dat b/testing/tests/tnc/tnccs-11-radius-pts/pretest.dat
index 31ee7d1..c96e063 100644
--- a/testing/tests/tnc/tnccs-11-radius-pts/pretest.dat
+++ b/testing/tests/tnc/tnccs-11-radius-pts/pretest.dat
@@ -11,12 +11,16 @@ alice::LEAK_DETECTIVE_DISABLE=1 LOG4CXX_CONFIGURATION=/etc/tnc/log4cxx.propertie
 alice::cat /etc/tnc_config
 carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
-moon::ipsec start
-dave::ipsec start
-carol::ipsec start
-dave::expect-connection home
-dave::ipsec up home
+carol::rm /etc/swanctl/rsa/*
+dave::rm /etc/swanctl/rsa/*
+carol::rm /etc/swanctl/x509/*
+dave::rm /etc/swanctl/x509/*
+moon::service charon start
+carol::service charon start
+dave::service charon start
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home
+dave::expect-connection home
+dave::swanctl --initiate --child home
 alice::ipsec attest --sessions
 alice::ipsec attest --devices
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/test.conf b/testing/tests/tnc/tnccs-11-radius-pts/test.conf
index 318dfdf..05d40f9 100644
--- a/testing/tests/tnc/tnccs-11-radius-pts/test.conf
+++ b/testing/tests/tnc/tnccs-11-radius-pts/test.conf
@@ -27,3 +27,7 @@ RADIUSHOSTS="alice"
 # Guest instances on which databases are used
 #
 DBHOSTS="alice"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-11-radius/evaltest.dat b/testing/tests/tnc/tnccs-11-radius/evaltest.dat
index 955584b..0415c33 100644
--- a/testing/tests/tnc/tnccs-11-radius/evaltest.dat
+++ b/testing/tests/tnc/tnccs-11-radius/evaltest.dat
@@ -1,19 +1,18 @@
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA.* successful::YES
 carol::cat /var/log/daemon.log::TNCCS-Recommendation.*allow::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
-carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/28::YES
 dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA.* successful::YES
 dave:: cat /var/log/daemon.log::TNCCS-Recommendation.*isolate::YES
 dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
-dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.16/28::YES
 moon:: cat /var/log/daemon.log::received RADIUS attribute Filter-Id: 'allow'::YES
 moon:: cat /var/log/daemon.log::authentication of 'carol at strongswan.org' with EAP successful::YES
 moon:: cat /var/log/daemon.log::received RADIUS attribute Filter-Id: 'isolate'::YES
 moon:: cat /var/log/daemon.log::authentication of 'dave at strongswan.org' with EAP successful::YES
-moon:: ipsec statusall 2> /dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.100/32::YES
-moon:: ipsec statusall 2> /dev/null::rw-isolate.*10.1.0.16/28 === 192.168.0.200/32::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.16/ [...]
+moon:: swanctl --list-sas --ike-id 1 --raw  2> /dev/null::rw-allow.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-allow.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/28] remote-ts=\[192.168. [...]
+moon:: swanctl --list-sas --ike-id 2 --raw  2> /dev/null::rw-isolate.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-isolate.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.16/28] remote-ts=\[192. [...]
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_ALICE: icmp_req=1::NO
+carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
 dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
-dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_VENUS: icmp_req=1::NO
-
+dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
diff --git a/testing/tests/tnc/tnccs-11-radius/hosts/alice/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-radius/hosts/alice/etc/strongswan.conf
index 45050f7..7622801 100644
--- a/testing/tests/tnc/tnccs-11-radius/hosts/alice/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11-radius/hosts/alice/etc/strongswan.conf
@@ -1,6 +1,7 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 libimcv {
+  load = random nonce sha1 sha2 md5 gmp pubkey x509
   debug_level = 3 
   assessment_result = no
   plugins {
diff --git a/testing/tests/tnc/tnccs-11-radius/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-11-radius/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index e9152e0..0000000
--- a/testing/tests/tnc/tnccs-11-radius/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightsubnet=10.1.0.0/16
-	rightauth=pubkey
-	aaa_identity="C=CH, O=Linux strongSwan, CN=aaa.strongswan.org"
-	auto=add
diff --git a/testing/tests/tnc/tnccs-11-radius/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11-radius/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 74942af..0000000
--- a/testing/tests/tnc/tnccs-11-radius/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol at strongswan.org : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-11-radius/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-radius/hosts/carol/etc/strongswan.conf
index 927c459..80c96b6 100644
--- a/testing/tests/tnc/tnccs-11-radius/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11-radius/hosts/carol/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
 
   multiple_authentication=no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+    }
+  }
   plugins {
     eap-tnc {
       protocol = tnccs-1.1
diff --git a/testing/tests/tnc/tnccs-11-radius/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-11-radius/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..ff58c7c
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11-radius/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap
+         aaa_id = aaa.strongswan.org
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = pubkey 
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-11-radius/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-11-radius/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 25589bc..0000000
--- a/testing/tests/tnc/tnccs-11-radius/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftid=dave at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightsubnet=10.1.0.0/16
-	rightauth=pubkey
-	aaa_identity="C=CH, O=Linux strongSwan, CN=aaa.strongswan.org"
-	auto=add
diff --git a/testing/tests/tnc/tnccs-11-radius/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11-radius/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index 5496df7..0000000
--- a/testing/tests/tnc/tnccs-11-radius/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-dave at strongswan.org : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-11-radius/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-radius/hosts/dave/etc/strongswan.conf
index 1422c3c..9c6f28f 100644
--- a/testing/tests/tnc/tnccs-11-radius/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11-radius/hosts/dave/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
+  load = random nonce aes sha1 sha2 md5 gmp hmac pem pkcs1 x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
 
   multiple_authentication=no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+    }
+  }
   plugins {
     eap-tnc {
       protocol = tnccs-1.1
diff --git a/testing/tests/tnc/tnccs-11-radius/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-11-radius/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..5af2098
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11-radius/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap
+         aaa_id = aaa.strongswan.org
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = pubkey 
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-11-radius/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-11-radius/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index 294964f..0000000
--- a/testing/tests/tnc/tnccs-11-radius/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,33 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=pubkey
-	leftfirewall=yes
-	rightauth=eap-radius
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
diff --git a/testing/tests/tnc/tnccs-11-radius/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11-radius/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index e86d6aa..0000000
--- a/testing/tests/tnc/tnccs-11-radius/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
diff --git a/testing/tests/tnc/tnccs-11-radius/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-radius/hosts/moon/etc/strongswan.conf
index 6e49677..71fc7dd 100644
--- a/testing/tests/tnc/tnccs-11-radius/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11-radius/hosts/moon/etc/strongswan.conf
@@ -1,12 +1,18 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-radius updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-radius updown
+
   multiple_authentication=no
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
   plugins {
     eap-radius {
       secret = gv6URkSs 
-      server = PH_IP_ALICE
+      server = 10.1.0.10 
       filter_id = yes
     }
   }
diff --git a/testing/tests/tnc/tnccs-11-radius/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-11-radius/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..3caad0c
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11-radius/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,53 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey 
+         id = moon.strongswan.org
+         certs = moonCert.pem
+      }
+      remote {
+         auth = eap-radius
+         id = *@strongswan.org
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey 
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-radius
+         id = *@strongswan.org
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/tnc/tnccs-11-radius/posttest.dat b/testing/tests/tnc/tnccs-11-radius/posttest.dat
index a64a914..2989f34 100644
--- a/testing/tests/tnc/tnccs-11-radius/posttest.dat
+++ b/testing/tests/tnc/tnccs-11-radius/posttest.dat
@@ -1,6 +1,6 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
 alice::killall radiusd
 alice::rm /etc/freeradius/sites-enabled/inner-tunnel-second
 moon::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-11-radius/pretest.dat b/testing/tests/tnc/tnccs-11-radius/pretest.dat
index fcfb145..baf8c97 100644
--- a/testing/tests/tnc/tnccs-11-radius/pretest.dat
+++ b/testing/tests/tnc/tnccs-11-radius/pretest.dat
@@ -7,10 +7,14 @@ alice::LEAK_DETECTIVE_DISABLE=1 LOG4CXX_CONFIGURATION=/etc/tnc/log4cxx.propertie
 alice::cat /etc/tnc_config
 carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+carol::rm /etc/swanctl/rsa/*
+dave::rm /etc/swanctl/rsa/*
+carol::rm /etc/swanctl/x509/*
+dave::rm /etc/swanctl/x509/*
+moon::service charon start
+carol::service charon start
+dave::service charon start
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home
diff --git a/testing/tests/tnc/tnccs-11-radius/test.conf b/testing/tests/tnc/tnccs-11-radius/test.conf
index f23a193..8d7f514 100644
--- a/testing/tests/tnc/tnccs-11-radius/test.conf
+++ b/testing/tests/tnc/tnccs-11-radius/test.conf
@@ -24,3 +24,6 @@ IPSECHOSTS="moon carol dave"
 #
 RADIUSHOSTS="alice"
 
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-11-supplicant/hosts/alice/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-supplicant/hosts/alice/etc/strongswan.conf
index 45050f7..7622801 100644
--- a/testing/tests/tnc/tnccs-11-supplicant/hosts/alice/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11-supplicant/hosts/alice/etc/strongswan.conf
@@ -1,6 +1,7 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 libimcv {
+  load = random nonce sha1 sha2 md5 gmp pubkey x509
   debug_level = 3 
   assessment_result = no
   plugins {
diff --git a/testing/tests/tnc/tnccs-11-supplicant/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-11-supplicant/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index f244559..0000000
--- a/testing/tests/tnc/tnccs-11-supplicant/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
diff --git a/testing/tests/tnc/tnccs-11-supplicant/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11-supplicant/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index ddd4956..0000000
--- a/testing/tests/tnc/tnccs-11-supplicant/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
diff --git a/testing/tests/tnc/tnccs-11-supplicant/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-supplicant/hosts/carol/etc/strongswan.conf
index 71fbae6..965752b 100644
--- a/testing/tests/tnc/tnccs-11-supplicant/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11-supplicant/hosts/carol/etc/strongswan.conf
@@ -1,6 +1,7 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 libimcv {
+  load = random nonce sha1 sha2 md5 gmp pubkey x509
   debug_level = 3
   plugins {
     imc-test {
diff --git a/testing/tests/tnc/tnccs-11-supplicant/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-11-supplicant/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..00ef0f5
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11-supplicant/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# The strongSwan IMCs are loaded by the WPA supplicant
diff --git a/testing/tests/tnc/tnccs-11-supplicant/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-11-supplicant/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index f244559..0000000
--- a/testing/tests/tnc/tnccs-11-supplicant/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
diff --git a/testing/tests/tnc/tnccs-11-supplicant/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11-supplicant/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index ddd4956..0000000
--- a/testing/tests/tnc/tnccs-11-supplicant/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
diff --git a/testing/tests/tnc/tnccs-11-supplicant/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-supplicant/hosts/dave/etc/strongswan.conf
index 4ce2769..ca1f7d9 100644
--- a/testing/tests/tnc/tnccs-11-supplicant/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11-supplicant/hosts/dave/etc/strongswan.conf
@@ -1,6 +1,7 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 libimcv {
+  load = random nonce sha1 sha2 md5 gmp pubkey x509
   debug_level = 3
   plugins {
     imc-test {
diff --git a/testing/tests/tnc/tnccs-11-supplicant/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-11-supplicant/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..00ef0f5
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11-supplicant/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# The strongSwan IMCs are loaded by the WPA supplicant
diff --git a/testing/tests/tnc/tnccs-11-supplicant/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-11-supplicant/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index 294964f..0000000
--- a/testing/tests/tnc/tnccs-11-supplicant/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,33 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=pubkey
-	leftfirewall=yes
-	rightauth=eap-radius
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
diff --git a/testing/tests/tnc/tnccs-11-supplicant/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11-supplicant/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index e86d6aa..0000000
--- a/testing/tests/tnc/tnccs-11-supplicant/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
diff --git a/testing/tests/tnc/tnccs-11-supplicant/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-11-supplicant/hosts/moon/etc/strongswan.conf
deleted file mode 100644
index 6e49677..0000000
--- a/testing/tests/tnc/tnccs-11-supplicant/hosts/moon/etc/strongswan.conf
+++ /dev/null
@@ -1,13 +0,0 @@
-# /etc/strongswan.conf - strongSwan configuration file
-
-charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-radius updown
-  multiple_authentication=no
-  plugins {
-    eap-radius {
-      secret = gv6URkSs 
-      server = PH_IP_ALICE
-      filter_id = yes
-    }
-  }
-}
diff --git a/testing/tests/tnc/tnccs-11-supplicant/test.conf b/testing/tests/tnc/tnccs-11-supplicant/test.conf
index f23a193..2069e4a 100644
--- a/testing/tests/tnc/tnccs-11-supplicant/test.conf
+++ b/testing/tests/tnc/tnccs-11-supplicant/test.conf
@@ -13,14 +13,17 @@ DIAGRAM="a-v-m-c-w-d.png"
 
 # Guest instances on which tcpdump is to be started
 #
-TCPDUMPHOSTS="moon"
+TCPDUMPHOSTS=
 
 # Guest instances on which IPsec is started
 # Used for IPsec logging purposes
 #
-IPSECHOSTS="moon carol dave"
+IPSECHOSTS="carol dave"
 
 # Guest instances on which FreeRadius is started
 #
 RADIUSHOSTS="alice"
 
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-11/evaltest.dat b/testing/tests/tnc/tnccs-11/evaltest.dat
index 3478c07..800fa3c 100644
--- a/testing/tests/tnc/tnccs-11/evaltest.dat
+++ b/testing/tests/tnc/tnccs-11/evaltest.dat
@@ -1,19 +1,18 @@
 carol::cat /var/log/daemon.log::TNCCS-Recommendation.*allow::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/28::YES
 dave:: cat /var/log/daemon.log::TNCCS-Recommendation.*isolate::YES
 dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.16/28::YES
 moon:: cat /var/log/daemon.log::added group membership 'allow'::YES
 moon:: cat /var/log/daemon.log::authentication of 'carol at strongswan.org' with EAP successful::YES
 moon:: cat /var/log/daemon.log::added group membership 'isolate'::YES
 moon:: cat /var/log/daemon.log::authentication of 'dave at strongswan.org' with EAP successful::YES
-moon:: ipsec statusall 2> /dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.100/32::YES
-moon:: ipsec statusall 2> /dev/null::rw-isolate.*10.1.0.16/28 === 192.168.0.200/32::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.16/ [...]
+moon:: swanctl --list-sas --ike-id 1 --raw  2> /dev/null::rw-allow.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-allow.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/28] remote-ts=\[192.168. [...]
+moon:: swanctl --list-sas --ike-id 2 --raw  2> /dev/null::rw-isolate.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-isolate.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.16/28] remote-ts=\[192. [...]
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_ALICE: icmp_req=1::NO
+carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
 dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
-dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_VENUS: icmp_req=1::NO
-
+dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
diff --git a/testing/tests/tnc/tnccs-11/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-11/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index e2bf349..0000000
--- a/testing/tests/tnc/tnccs-11/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-11/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 74942af..0000000
--- a/testing/tests/tnc/tnccs-11/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol at strongswan.org : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-11/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-11/hosts/carol/etc/strongswan.conf
index 927c459..af30c20 100644
--- a/testing/tests/tnc/tnccs-11/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11/hosts/carol/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
 
   multiple_authentication=no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+    }
+  }
   plugins {
     eap-tnc {
       protocol = tnccs-1.1
@@ -12,6 +25,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-test {
diff --git a/testing/tests/tnc/tnccs-11/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-11/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..0f266dd
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-11/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-11/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 77446cb..0000000
--- a/testing/tests/tnc/tnccs-11/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftid=dave at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-11/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index 5496df7..0000000
--- a/testing/tests/tnc/tnccs-11/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-dave at strongswan.org : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-11/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-11/hosts/dave/etc/strongswan.conf
index 1422c3c..5245362 100644
--- a/testing/tests/tnc/tnccs-11/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11/hosts/dave/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
+  load = random nonce aes sha1 sha2 md5 gmp hmac pem pkcs1 x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
 
   multiple_authentication=no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+    }
+  }
   plugins {
     eap-tnc {
       protocol = tnccs-1.1
@@ -12,6 +25,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-test {
diff --git a/testing/tests/tnc/tnccs-11/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-11/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..989ab88
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-11/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-11/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index e21ef0d..0000000
--- a/testing/tests/tnc/tnccs-11/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,34 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imv 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=eap-ttls
-	leftfirewall=yes
-	rightauth=eap-ttls
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
diff --git a/testing/tests/tnc/tnccs-11/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-11/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index 2e277cc..0000000
--- a/testing/tests/tnc/tnccs-11/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
-
-carol at strongswan.org : EAP "Ar3etTnp"
-dave at strongswan.org  : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-11/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-11/hosts/moon/etc/strongswan.conf
index 2ce6fd3..bba631b 100644
--- a/testing/tests/tnc/tnccs-11/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11/hosts/moon/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-11 tnc-imv updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-11 tnc-imv updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imv = 3
+    }
+  }
   plugins {
     eap-ttls {
       phase2_method = md5
@@ -18,6 +31,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imv-test {
diff --git a/testing/tests/tnc/tnccs-11/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-11/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..1238c1a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-11/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,64 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap-carol {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+   eap-dave {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-11/posttest.dat b/testing/tests/tnc/tnccs-11/posttest.dat
index 1865a1c..770cf6e 100644
--- a/testing/tests/tnc/tnccs-11/posttest.dat
+++ b/testing/tests/tnc/tnccs-11/posttest.dat
@@ -1,6 +1,6 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-11/pretest.dat b/testing/tests/tnc/tnccs-11/pretest.dat
index 8562203..c8ab143 100644
--- a/testing/tests/tnc/tnccs-11/pretest.dat
+++ b/testing/tests/tnc/tnccs-11/pretest.dat
@@ -4,10 +4,14 @@ dave::iptables-restore < /etc/iptables.rules
 moon::cat /etc/tnc_config
 carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+carol::rm /etc/swanctl/rsa/*
+dave::rm /etc/swanctl/rsa/*
+carol::rm /etc/swanctl/x509/*
+dave::rm /etc/swanctl/x509/*
+moon::service charon start
+carol::service charon start
+dave::service charon start
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/tnc/tnccs-11/test.conf b/testing/tests/tnc/tnccs-11/test.conf
index a8a05af..3a66699 100644
--- a/testing/tests/tnc/tnccs-11/test.conf
+++ b/testing/tests/tnc/tnccs-11/test.conf
@@ -24,3 +24,7 @@ IPSECHOSTS="moon carol dave"
 #
 RADIUSHOSTS=
 
+# charon controlled by swanctl
+#
+SWANCTL=1
+
diff --git a/testing/tests/tnc/tnccs-20-block/evaltest.dat b/testing/tests/tnc/tnccs-20-block/evaltest.dat
index e0f3d93..b67affb 100644
--- a/testing/tests/tnc/tnccs-20-block/evaltest.dat
+++ b/testing/tests/tnc/tnccs-20-block/evaltest.dat
@@ -1,12 +1,14 @@
 carol::cat /var/log/daemon.log::PB-TNC access recommendation is 'Access Allowed'::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/16::YES
 dave:: cat /var/log/daemon.log::PB-TNC access recommendation is 'Access Denied'::YES
 dave:: cat /var/log/daemon.log::received EAP_FAILURE, EAP authentication failed::YES
-dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.0/16::NO
 moon:: cat /var/log/daemon.log::added group membership 'allow'::YES
 moon:: cat /var/log/daemon.log::authentication of 'carol at strongswan.org' with EAP successful::YES
 moon:: cat /var/log/daemon.log::EAP method EAP_TTLS failed for peer dave at strongswan.org::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home::NO
+moon:: swanctl --list-sas --ike-id 1 --raw  2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]::YES
+moon:: swanctl --list-sas --ike-id 2 --raw  2> /dev/null::rw::NO
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_VENUS: icmp_req=1::NO
+dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
diff --git a/testing/tests/tnc/tnccs-20-block/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-block/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index e2bf349..0000000
--- a/testing/tests/tnc/tnccs-20-block/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-block/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-block/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 74942af..0000000
--- a/testing/tests/tnc/tnccs-20-block/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol at strongswan.org : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-20-block/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-block/hosts/carol/etc/strongswan.conf
index 201f6c7..fac3dc0 100644
--- a/testing/tests/tnc/tnccs-20-block/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-block/hosts/carol/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+    }
+  }
   plugins {
     tnc-imc {
       preferred_language = de, en
@@ -12,6 +25,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-test {
diff --git a/testing/tests/tnc/tnccs-20-block/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-block/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..760fca4
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-block/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,34 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = eap-ttls 
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-block/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-block/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 77446cb..0000000
--- a/testing/tests/tnc/tnccs-20-block/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftid=dave at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-block/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-block/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index 5496df7..0000000
--- a/testing/tests/tnc/tnccs-20-block/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-dave at strongswan.org : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-block/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-block/hosts/dave/etc/strongswan.conf
index a255b90..168e4ec 100644
--- a/testing/tests/tnc/tnccs-20-block/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-block/hosts/dave/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
   multiple_authentication=no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+    }
+  }
   plugins {
     tnc-imc {
       preferred_language = ru, fr, en
@@ -12,6 +25,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-scanner {
diff --git a/testing/tests/tnc/tnccs-20-block/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-block/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..5345003
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-block/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,34 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-block/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-block/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index 9aeb02a..0000000
--- a/testing/tests/tnc/tnccs-20-block/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,24 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imv 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftsubnet=10.1.0.0/16
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=eap-ttls
-	leftfirewall=yes
-	rightauth=eap-ttls
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-block/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-block/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index 2e277cc..0000000
--- a/testing/tests/tnc/tnccs-20-block/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
-
-carol at strongswan.org : EAP "Ar3etTnp"
-dave at strongswan.org  : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-block/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-block/hosts/moon/etc/strongswan.conf
index ee510f1..bb15d3f 100644
--- a/testing/tests/tnc/tnccs-20-block/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-block/hosts/moon/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-20 tnc-imv updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-20 tnc-imv updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imv = 3
+    }
+  }
   plugins {
     eap-ttls {
       phase2_method = md5
@@ -17,12 +30,6 @@ charon {
   }
 }
 
-libimcv {
-  plugins {
-    imv-scanner {
-      closed_port_policy = yes
-      tcp_ports = 22
-      udp_ports = 500 4500
-    }
-  }
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
 }
diff --git a/testing/tests/tnc/tnccs-20-block/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-block/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..e396cd0
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-block/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,39 @@
+connections {
+
+   rw {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls 
+         id = moon.strongswan.org
+         certs = moonCert.pem
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+      }
+      children {
+         rw {
+            local_ts = 10.1.0.0/16
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap-carol {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+   eap-dave {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-block/posttest.dat b/testing/tests/tnc/tnccs-20-block/posttest.dat
index 2258e03..770cf6e 100644
--- a/testing/tests/tnc/tnccs-20-block/posttest.dat
+++ b/testing/tests/tnc/tnccs-20-block/posttest.dat
@@ -1,7 +1,6 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
-dave::/etc/init.d/apache2 stop 2> /dev/null
diff --git a/testing/tests/tnc/tnccs-20-block/pretest.dat b/testing/tests/tnc/tnccs-20-block/pretest.dat
index c66a2e1..c8ab143 100644
--- a/testing/tests/tnc/tnccs-20-block/pretest.dat
+++ b/testing/tests/tnc/tnccs-20-block/pretest.dat
@@ -1,14 +1,17 @@
 moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
 dave::iptables-restore < /etc/iptables.rules
-dave::/etc/init.d/apache2 start 2> /dev/null
 moon::cat /etc/tnc_config
 carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+carol::rm /etc/swanctl/rsa/*
+dave::rm /etc/swanctl/rsa/*
+carol::rm /etc/swanctl/x509/*
+dave::rm /etc/swanctl/x509/*
+moon::service charon start
+carol::service charon start
+dave::service charon start
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/tnc/tnccs-20-block/test.conf b/testing/tests/tnc/tnccs-20-block/test.conf
index a8a05af..f6db739 100644
--- a/testing/tests/tnc/tnccs-20-block/test.conf
+++ b/testing/tests/tnc/tnccs-20-block/test.conf
@@ -24,3 +24,6 @@ IPSECHOSTS="moon carol dave"
 #
 RADIUSHOSTS=
 
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-20-client-retry/evaltest.dat b/testing/tests/tnc/tnccs-20-client-retry/evaltest.dat
index c69940c..1b70ac8 100644
--- a/testing/tests/tnc/tnccs-20-client-retry/evaltest.dat
+++ b/testing/tests/tnc/tnccs-20-client-retry/evaltest.dat
@@ -1,19 +1,17 @@
 carol::cat /var/log/daemon.log::PB-TNC access recommendation is 'Access Allowed'::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
-carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/28::YES
 dave:: cat /var/log/daemon.log::PB-TNC access recommendation is 'Quarantined'::YES
 dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.16/28::YES
 moon:: cat /var/log/daemon.log::added group membership 'allow'::YES
 moon:: cat /var/log/daemon.log::authentication of 'carol at strongswan.org' with EAP successful::YES
 moon:: cat /var/log/daemon.log::added group membership 'isolate'::YES
 moon:: cat /var/log/daemon.log::authentication of 'dave at strongswan.org' with EAP successful::YES
-moon:: ipsec statusall 2> /dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.100/32::YES
-moon:: ipsec statusall 2> /dev/null::rw-isolate.*10.1.0.16/28 === 192.168.0.200/32::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.16/ [...]
+moon:: swanctl --list-sas --ike-id 1 --raw  2> /dev/null::rw-allow.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-allow.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/28] remote-ts=\[192.168. [...]
+moon:: swanctl --list-sas --ike-id 2 --raw  2> /dev/null::rw-isolate.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-isolate.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.16/28] remote-ts=\[192. [...]
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_ALICE: icmp_req=1::NO
+carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
 dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
-dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_VENUS: icmp_req=1::NO
-
+dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
diff --git a/testing/tests/tnc/tnccs-20-client-retry/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-client-retry/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index a483d6d..0000000
--- a/testing/tests/tnc/tnccs-20-client-retry/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 2"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-client-retry/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-client-retry/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 74942af..0000000
--- a/testing/tests/tnc/tnccs-20-client-retry/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol at strongswan.org : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-20-client-retry/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-client-retry/hosts/carol/etc/strongswan.conf
index ea8e626..aceddc3 100644
--- a/testing/tests/tnc/tnccs-20-client-retry/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-client-retry/hosts/carol/etc/strongswan.conf
@@ -1,9 +1,27 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 2 
+    }
+  }
+}
+
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
 }
 
 libimcv {
diff --git a/testing/tests/tnc/tnccs-20-client-retry/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-client-retry/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..0f266dd
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-client-retry/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-client-retry/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-client-retry/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 1137813..0000000
--- a/testing/tests/tnc/tnccs-20-client-retry/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 2"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftid=dave at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-client-retry/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-client-retry/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index 5496df7..0000000
--- a/testing/tests/tnc/tnccs-20-client-retry/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-dave at strongswan.org : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-client-retry/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-client-retry/hosts/dave/etc/strongswan.conf
index 3a93fc3..7ac1a5d 100644
--- a/testing/tests/tnc/tnccs-20-client-retry/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-client-retry/hosts/dave/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 2 
+    }
+  }
   plugins {
     tnc-imc {
       preferred_language = ru , de, en
@@ -12,6 +25,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-test {
diff --git a/testing/tests/tnc/tnccs-20-client-retry/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-client-retry/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..989ab88
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-client-retry/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-client-retry/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-client-retry/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index b1093d4..0000000
--- a/testing/tests/tnc/tnccs-20-client-retry/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,34 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imv 2"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=eap-ttls
-	leftfirewall=yes
-	rightauth=eap-ttls
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
diff --git a/testing/tests/tnc/tnccs-20-client-retry/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-client-retry/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index 2e277cc..0000000
--- a/testing/tests/tnc/tnccs-20-client-retry/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
-
-carol at strongswan.org : EAP "Ar3etTnp"
-dave at strongswan.org  : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-client-retry/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-client-retry/hosts/moon/etc/strongswan.conf
index 009e2ef..a0b8077 100644
--- a/testing/tests/tnc/tnccs-20-client-retry/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-client-retry/hosts/moon/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-20 tnc-imv updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-20 tnc-imv updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imv = 2
+    }
+  }
   plugins {
     eap-ttls {
       phase2_method = md5
@@ -14,6 +27,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imv-test {
diff --git a/testing/tests/tnc/tnccs-20-client-retry/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-client-retry/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..1238c1a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-client-retry/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,64 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap-carol {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+   eap-dave {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-client-retry/posttest.dat b/testing/tests/tnc/tnccs-20-client-retry/posttest.dat
index 1865a1c..770cf6e 100644
--- a/testing/tests/tnc/tnccs-20-client-retry/posttest.dat
+++ b/testing/tests/tnc/tnccs-20-client-retry/posttest.dat
@@ -1,6 +1,6 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-20-client-retry/pretest.dat b/testing/tests/tnc/tnccs-20-client-retry/pretest.dat
index 8562203..c8ab143 100644
--- a/testing/tests/tnc/tnccs-20-client-retry/pretest.dat
+++ b/testing/tests/tnc/tnccs-20-client-retry/pretest.dat
@@ -4,10 +4,14 @@ dave::iptables-restore < /etc/iptables.rules
 moon::cat /etc/tnc_config
 carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+carol::rm /etc/swanctl/rsa/*
+dave::rm /etc/swanctl/rsa/*
+carol::rm /etc/swanctl/x509/*
+dave::rm /etc/swanctl/x509/*
+moon::service charon start
+carol::service charon start
+dave::service charon start
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/tnc/tnccs-20-client-retry/test.conf b/testing/tests/tnc/tnccs-20-client-retry/test.conf
index a8a05af..f6db739 100644
--- a/testing/tests/tnc/tnccs-20-client-retry/test.conf
+++ b/testing/tests/tnc/tnccs-20-client-retry/test.conf
@@ -24,3 +24,6 @@ IPSECHOSTS="moon carol dave"
 #
 RADIUSHOSTS=
 
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-20-fail-init/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-fail-init/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index e2bf349..0000000
--- a/testing/tests/tnc/tnccs-20-fail-init/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-fail-init/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-fail-init/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 74942af..0000000
--- a/testing/tests/tnc/tnccs-20-fail-init/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol at strongswan.org : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-20-fail-init/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-fail-init/hosts/carol/etc/strongswan.conf
index fcd2246..0733557 100644
--- a/testing/tests/tnc/tnccs-20-fail-init/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-fail-init/hosts/carol/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+    }
+  }
   plugins {
     tnccs-20 {
       tests {
@@ -14,6 +27,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-test {
diff --git a/testing/tests/tnc/tnccs-20-fail-init/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-fail-init/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..0f266dd
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-fail-init/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-fail-init/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-fail-init/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 5044084..0000000
--- a/testing/tests/tnc/tnccs-20-fail-init/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftid=dave at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-fail-init/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-fail-init/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index 5496df7..0000000
--- a/testing/tests/tnc/tnccs-20-fail-init/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-dave at strongswan.org : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-fail-init/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-fail-init/hosts/dave/etc/strongswan.conf
index 76f4137..6c1b991 100644
--- a/testing/tests/tnc/tnccs-20-fail-init/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-fail-init/hosts/dave/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+    }
+  }
   plugins {
     tnc-imc {
       preferred_language = ru, pl  , de
@@ -17,6 +30,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-test {
diff --git a/testing/tests/tnc/tnccs-20-fail-init/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-fail-init/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..989ab88
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-fail-init/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-fail-init/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-fail-init/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index e21ef0d..0000000
--- a/testing/tests/tnc/tnccs-20-fail-init/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,34 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imv 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=eap-ttls
-	leftfirewall=yes
-	rightauth=eap-ttls
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
diff --git a/testing/tests/tnc/tnccs-20-fail-init/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-fail-init/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index 2e277cc..0000000
--- a/testing/tests/tnc/tnccs-20-fail-init/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
-
-carol at strongswan.org : EAP "Ar3etTnp"
-dave at strongswan.org  : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-fail-init/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-fail-init/hosts/moon/etc/strongswan.conf
index 9c13fcb..165c5cc 100644
--- a/testing/tests/tnc/tnccs-20-fail-init/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-fail-init/hosts/moon/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imv = 3
+    }
+  }
   plugins {
     eap-ttls {
       phase2_method = md5
@@ -14,6 +27,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imv-test {
diff --git a/testing/tests/tnc/tnccs-20-fail-init/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-fail-init/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..1238c1a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-fail-init/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,64 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap-carol {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+   eap-dave {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-fail-init/posttest.dat b/testing/tests/tnc/tnccs-20-fail-init/posttest.dat
index b757d8b..770cf6e 100644
--- a/testing/tests/tnc/tnccs-20-fail-init/posttest.dat
+++ b/testing/tests/tnc/tnccs-20-fail-init/posttest.dat
@@ -1,6 +1,6 @@
-carol::ipsec stop
-dave::ipsec stop
-moon::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-20-fail-init/pretest.dat b/testing/tests/tnc/tnccs-20-fail-init/pretest.dat
index 8562203..c8ab143 100644
--- a/testing/tests/tnc/tnccs-20-fail-init/pretest.dat
+++ b/testing/tests/tnc/tnccs-20-fail-init/pretest.dat
@@ -4,10 +4,14 @@ dave::iptables-restore < /etc/iptables.rules
 moon::cat /etc/tnc_config
 carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+carol::rm /etc/swanctl/rsa/*
+dave::rm /etc/swanctl/rsa/*
+carol::rm /etc/swanctl/x509/*
+dave::rm /etc/swanctl/x509/*
+moon::service charon start
+carol::service charon start
+dave::service charon start
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/tnc/tnccs-20-fail-init/test.conf b/testing/tests/tnc/tnccs-20-fail-init/test.conf
index 3c8e399..5131149 100644
--- a/testing/tests/tnc/tnccs-20-fail-init/test.conf
+++ b/testing/tests/tnc/tnccs-20-fail-init/test.conf
@@ -24,3 +24,6 @@ IPSECHOSTS="moon carol dave"
 #
 RADIUSHOSTS=
 
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-20-fail-resp/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-fail-resp/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index e2bf349..0000000
--- a/testing/tests/tnc/tnccs-20-fail-resp/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-fail-resp/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-fail-resp/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 74942af..0000000
--- a/testing/tests/tnc/tnccs-20-fail-resp/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol at strongswan.org : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-20-fail-resp/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-fail-resp/hosts/carol/etc/strongswan.conf
index ed6d6f7..56fa7a9 100644
--- a/testing/tests/tnc/tnccs-20-fail-resp/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-fail-resp/hosts/carol/etc/strongswan.conf
@@ -1,9 +1,27 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
 
   multiple_authentication = no
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+    }
+  }
+}
+
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
 }
 
 libimcv {
diff --git a/testing/tests/tnc/tnccs-20-fail-resp/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-fail-resp/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..0f266dd
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-fail-resp/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-fail-resp/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-fail-resp/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index e21ef0d..0000000
--- a/testing/tests/tnc/tnccs-20-fail-resp/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,34 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imv 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=eap-ttls
-	leftfirewall=yes
-	rightauth=eap-ttls
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
diff --git a/testing/tests/tnc/tnccs-20-fail-resp/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-fail-resp/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index 2e277cc..0000000
--- a/testing/tests/tnc/tnccs-20-fail-resp/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
-
-carol at strongswan.org : EAP "Ar3etTnp"
-dave at strongswan.org  : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-fail-resp/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-fail-resp/hosts/moon/etc/strongswan.conf
index 626731f..cb6abf3 100644
--- a/testing/tests/tnc/tnccs-20-fail-resp/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-fail-resp/hosts/moon/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imv = 3
+    }
+  }
   plugins {
     eap-ttls {
       phase2_method = md5
@@ -19,6 +32,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imv-test {
diff --git a/testing/tests/tnc/tnccs-20-fail-resp/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-fail-resp/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..1238c1a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-fail-resp/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,64 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap-carol {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+   eap-dave {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-fail-resp/posttest.dat b/testing/tests/tnc/tnccs-20-fail-resp/posttest.dat
index 80ce1a1..9af5f39 100644
--- a/testing/tests/tnc/tnccs-20-fail-resp/posttest.dat
+++ b/testing/tests/tnc/tnccs-20-fail-resp/posttest.dat
@@ -1,4 +1,4 @@
-carol::ipsec stop
-moon::ipsec stop
+carol::service charon stop
+moon::service charon stop
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-20-fail-resp/pretest.dat b/testing/tests/tnc/tnccs-20-fail-resp/pretest.dat
index e5c2029..3dba1d7 100644
--- a/testing/tests/tnc/tnccs-20-fail-resp/pretest.dat
+++ b/testing/tests/tnc/tnccs-20-fail-resp/pretest.dat
@@ -2,7 +2,9 @@ moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
 moon::cat /etc/tnc_config
 carol::cat /etc/tnc_config
-moon::ipsec start
-carol::ipsec start
+carol::rm /etc/swanctl/rsa/*
+carol::rm /etc/swanctl/x509/*
+moon::service charon start
+carol::service charon start
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/tnc/tnccs-20-fail-resp/test.conf b/testing/tests/tnc/tnccs-20-fail-resp/test.conf
index e843074..9141c69 100644
--- a/testing/tests/tnc/tnccs-20-fail-resp/test.conf
+++ b/testing/tests/tnc/tnccs-20-fail-resp/test.conf
@@ -24,3 +24,6 @@ IPSECHOSTS="moon carol"
 #
 RADIUSHOSTS=
 
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-20-fhh/evaltest.dat b/testing/tests/tnc/tnccs-20-fhh/evaltest.dat
index c69940c..d406b59 100644
--- a/testing/tests/tnc/tnccs-20-fhh/evaltest.dat
+++ b/testing/tests/tnc/tnccs-20-fhh/evaltest.dat
@@ -1,19 +1,18 @@
-carol::cat /var/log/daemon.log::PB-TNC access recommendation is 'Access Allowed'::YES
+carol::cat /var/log/daemon.log::PB-TNC access recommendation is.*Access Allowed::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/28::YES
-dave:: cat /var/log/daemon.log::PB-TNC access recommendation is 'Quarantined'::YES
+dave:: cat /var/log/daemon.log::PB-TNC access recommendation is.*Quarantined::YES
 dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.16/28::YES
 moon:: cat /var/log/daemon.log::added group membership 'allow'::YES
 moon:: cat /var/log/daemon.log::authentication of 'carol at strongswan.org' with EAP successful::YES
 moon:: cat /var/log/daemon.log::added group membership 'isolate'::YES
 moon:: cat /var/log/daemon.log::authentication of 'dave at strongswan.org' with EAP successful::YES
-moon:: ipsec statusall 2> /dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.100/32::YES
-moon:: ipsec statusall 2> /dev/null::rw-isolate.*10.1.0.16/28 === 192.168.0.200/32::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.16/ [...]
+moon:: swanctl --list-sas --ike-id 1 --raw  2> /dev/null::rw-allow.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-allow.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/28] remote-ts=\[192.168. [...]
+moon:: swanctl --list-sas --ike-id 2 --raw  2> /dev/null::rw-isolate.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-isolate.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.16/28] remote-ts=\[192. [...]
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_ALICE: icmp_req=1::NO
+carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
 dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
-dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_VENUS: icmp_req=1::NO
-
+dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
diff --git a/testing/tests/tnc/tnccs-20-fhh/hosts/carol/etc/init.d/charon b/testing/tests/tnc/tnccs-20-fhh/hosts/carol/etc/init.d/charon
new file mode 100755
index 0000000..bf3a689
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-fhh/hosts/carol/etc/init.d/charon
@@ -0,0 +1,158 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          charon 
+# Required-Start:    $remote_fs $syslog
+# Required-Stop:     $remote_fs $syslog
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: strongSwan charon IKE daemon 
+# Description:       with swanctl the strongSwan charon daemon must be
+#                    running in the background
+### END INIT INFO
+
+# Author: Andreas Steffen <andreas.steffen at strongswa.org>
+#
+# Do NOT "set -e"
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin
+DESC="strongSwan charon IKE daemon"
+NAME=charon
+DAEMON=/usr/local/libexec/ipsec/$NAME
+DAEMON_ARGS=""
+PIDFILE=/var/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/charon
+
+export LOG4CXX_CONFIGURATION=/etc/tnc/log4cxx.properties
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcS variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
+# and status_of_proc is working.
+. /lib/lsb/init-functions
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+	# Return
+	#   0 if daemon has been started
+	#   1 if daemon was already running
+	#   2 if daemon could not be started
+	start-stop-daemon --start --quiet --background --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
+		|| return 1
+	start-stop-daemon --start --quiet --background --pidfile $PIDFILE --exec $DAEMON -- \
+		$DAEMON_ARGS \
+		|| return 2
+	# Add code here, if necessary, that waits for the process to be ready
+	# to handle requests from services started subsequently which depend
+	# on this one.  As a last resort, sleep for some time.
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+	# Return
+	#   0 if daemon has been stopped
+	#   1 if daemon was already stopped
+	#   2 if daemon could not be stopped
+	#   other if a failure occurred
+	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
+	RETVAL="$?"
+	[ "$RETVAL" = 2 ] && return 2
+	# Wait for children to finish too if this is a daemon that forks
+	# and if the daemon is only ever run from this initscript.
+	# If the above conditions are not satisfied then add some other code
+	# that waits for the process to drop all resources that could be
+	# needed by services started subsequently.  A last resort is to
+	# sleep for some time.
+	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
+	[ "$?" = 2 ] && return 2
+	# Many daemons don't delete their pidfiles when they exit.
+	rm -f $PIDFILE
+	return "$RETVAL"
+}
+
+#
+# Function that sends a SIGHUP to the daemon/service
+#
+do_reload() {
+	#
+	# If the daemon can reload its configuration without
+	# restarting (for example, when it is sent a SIGHUP),
+	# then implement that here.
+	#
+	start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
+	return 0
+}
+
+case "$1" in
+  start)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+	do_start
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  stop)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+	do_stop
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  status)
+	status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
+	;;
+  #reload|force-reload)
+	#
+	# If do_reload() is not implemented then leave this commented out
+	# and leave 'force-reload' as an alias for 'restart'.
+	#
+	#log_daemon_msg "Reloading $DESC" "$NAME"
+	#do_reload
+	#log_end_msg $?
+	#;;
+  restart|force-reload)
+	#
+	# If the "reload" option is implemented then remove the
+	# 'force-reload' alias
+	#
+	log_daemon_msg "Restarting $DESC" "$NAME"
+	do_stop
+	case "$?" in
+	  0|1)
+		do_start
+		case "$?" in
+			0) log_end_msg 0 ;;
+			1) log_end_msg 1 ;; # Old process is still running
+			*) log_end_msg 1 ;; # Failed to start
+		esac
+		;;
+	  *)
+		# Failed to stop
+		log_end_msg 1
+		;;
+	esac
+	;;
+  *)
+	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+	echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
+	exit 3
+	;;
+esac
+
+:
diff --git a/testing/tests/tnc/tnccs-20-fhh/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-fhh/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index a483d6d..0000000
--- a/testing/tests/tnc/tnccs-20-fhh/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 2"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-fhh/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-fhh/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 74942af..0000000
--- a/testing/tests/tnc/tnccs-20-fhh/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol at strongswan.org : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-20-fhh/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-fhh/hosts/carol/etc/strongswan.conf
index 43af0fc..c3338d4 100644
--- a/testing/tests/tnc/tnccs-20-fhh/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-fhh/hosts/carol/etc/strongswan.conf
@@ -1,7 +1,25 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 2 
+    }
+  }
+}
+
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
 }
diff --git a/testing/tests/tnc/tnccs-20-fhh/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-fhh/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..0f266dd
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-fhh/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-fhh/hosts/dave/etc/init.d/charon b/testing/tests/tnc/tnccs-20-fhh/hosts/dave/etc/init.d/charon
new file mode 100755
index 0000000..bf3a689
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-fhh/hosts/dave/etc/init.d/charon
@@ -0,0 +1,158 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          charon 
+# Required-Start:    $remote_fs $syslog
+# Required-Stop:     $remote_fs $syslog
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: strongSwan charon IKE daemon 
+# Description:       with swanctl the strongSwan charon daemon must be
+#                    running in the background
+### END INIT INFO
+
+# Author: Andreas Steffen <andreas.steffen at strongswa.org>
+#
+# Do NOT "set -e"
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin
+DESC="strongSwan charon IKE daemon"
+NAME=charon
+DAEMON=/usr/local/libexec/ipsec/$NAME
+DAEMON_ARGS=""
+PIDFILE=/var/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/charon
+
+export LOG4CXX_CONFIGURATION=/etc/tnc/log4cxx.properties
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcS variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
+# and status_of_proc is working.
+. /lib/lsb/init-functions
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+	# Return
+	#   0 if daemon has been started
+	#   1 if daemon was already running
+	#   2 if daemon could not be started
+	start-stop-daemon --start --quiet --background --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
+		|| return 1
+	start-stop-daemon --start --quiet --background --pidfile $PIDFILE --exec $DAEMON -- \
+		$DAEMON_ARGS \
+		|| return 2
+	# Add code here, if necessary, that waits for the process to be ready
+	# to handle requests from services started subsequently which depend
+	# on this one.  As a last resort, sleep for some time.
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+	# Return
+	#   0 if daemon has been stopped
+	#   1 if daemon was already stopped
+	#   2 if daemon could not be stopped
+	#   other if a failure occurred
+	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
+	RETVAL="$?"
+	[ "$RETVAL" = 2 ] && return 2
+	# Wait for children to finish too if this is a daemon that forks
+	# and if the daemon is only ever run from this initscript.
+	# If the above conditions are not satisfied then add some other code
+	# that waits for the process to drop all resources that could be
+	# needed by services started subsequently.  A last resort is to
+	# sleep for some time.
+	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
+	[ "$?" = 2 ] && return 2
+	# Many daemons don't delete their pidfiles when they exit.
+	rm -f $PIDFILE
+	return "$RETVAL"
+}
+
+#
+# Function that sends a SIGHUP to the daemon/service
+#
+do_reload() {
+	#
+	# If the daemon can reload its configuration without
+	# restarting (for example, when it is sent a SIGHUP),
+	# then implement that here.
+	#
+	start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
+	return 0
+}
+
+case "$1" in
+  start)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+	do_start
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  stop)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+	do_stop
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  status)
+	status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
+	;;
+  #reload|force-reload)
+	#
+	# If do_reload() is not implemented then leave this commented out
+	# and leave 'force-reload' as an alias for 'restart'.
+	#
+	#log_daemon_msg "Reloading $DESC" "$NAME"
+	#do_reload
+	#log_end_msg $?
+	#;;
+  restart|force-reload)
+	#
+	# If the "reload" option is implemented then remove the
+	# 'force-reload' alias
+	#
+	log_daemon_msg "Restarting $DESC" "$NAME"
+	do_stop
+	case "$?" in
+	  0|1)
+		do_start
+		case "$?" in
+			0) log_end_msg 0 ;;
+			1) log_end_msg 1 ;; # Old process is still running
+			*) log_end_msg 1 ;; # Failed to start
+		esac
+		;;
+	  *)
+		# Failed to stop
+		log_end_msg 1
+		;;
+	esac
+	;;
+  *)
+	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+	echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
+	exit 3
+	;;
+esac
+
+:
diff --git a/testing/tests/tnc/tnccs-20-fhh/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-fhh/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 1137813..0000000
--- a/testing/tests/tnc/tnccs-20-fhh/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 2"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftid=dave at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-fhh/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-fhh/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index 5496df7..0000000
--- a/testing/tests/tnc/tnccs-20-fhh/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-dave at strongswan.org : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-fhh/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-fhh/hosts/dave/etc/strongswan.conf
index 43af0fc..89d9e50 100644
--- a/testing/tests/tnc/tnccs-20-fhh/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-fhh/hosts/dave/etc/strongswan.conf
@@ -1,7 +1,24 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 2 
+    }
+  }
+}
+
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
 }
diff --git a/testing/tests/tnc/tnccs-20-fhh/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-fhh/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..989ab88
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-fhh/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-fhh/hosts/moon/etc/init.d/charon b/testing/tests/tnc/tnccs-20-fhh/hosts/moon/etc/init.d/charon
new file mode 100755
index 0000000..bf3a689
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-fhh/hosts/moon/etc/init.d/charon
@@ -0,0 +1,158 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          charon 
+# Required-Start:    $remote_fs $syslog
+# Required-Stop:     $remote_fs $syslog
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: strongSwan charon IKE daemon 
+# Description:       with swanctl the strongSwan charon daemon must be
+#                    running in the background
+### END INIT INFO
+
+# Author: Andreas Steffen <andreas.steffen at strongswa.org>
+#
+# Do NOT "set -e"
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin
+DESC="strongSwan charon IKE daemon"
+NAME=charon
+DAEMON=/usr/local/libexec/ipsec/$NAME
+DAEMON_ARGS=""
+PIDFILE=/var/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/charon
+
+export LOG4CXX_CONFIGURATION=/etc/tnc/log4cxx.properties
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcS variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
+# and status_of_proc is working.
+. /lib/lsb/init-functions
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+	# Return
+	#   0 if daemon has been started
+	#   1 if daemon was already running
+	#   2 if daemon could not be started
+	start-stop-daemon --start --quiet --background --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
+		|| return 1
+	start-stop-daemon --start --quiet --background --pidfile $PIDFILE --exec $DAEMON -- \
+		$DAEMON_ARGS \
+		|| return 2
+	# Add code here, if necessary, that waits for the process to be ready
+	# to handle requests from services started subsequently which depend
+	# on this one.  As a last resort, sleep for some time.
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+	# Return
+	#   0 if daemon has been stopped
+	#   1 if daemon was already stopped
+	#   2 if daemon could not be stopped
+	#   other if a failure occurred
+	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
+	RETVAL="$?"
+	[ "$RETVAL" = 2 ] && return 2
+	# Wait for children to finish too if this is a daemon that forks
+	# and if the daemon is only ever run from this initscript.
+	# If the above conditions are not satisfied then add some other code
+	# that waits for the process to drop all resources that could be
+	# needed by services started subsequently.  A last resort is to
+	# sleep for some time.
+	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
+	[ "$?" = 2 ] && return 2
+	# Many daemons don't delete their pidfiles when they exit.
+	rm -f $PIDFILE
+	return "$RETVAL"
+}
+
+#
+# Function that sends a SIGHUP to the daemon/service
+#
+do_reload() {
+	#
+	# If the daemon can reload its configuration without
+	# restarting (for example, when it is sent a SIGHUP),
+	# then implement that here.
+	#
+	start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
+	return 0
+}
+
+case "$1" in
+  start)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+	do_start
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  stop)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+	do_stop
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  status)
+	status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
+	;;
+  #reload|force-reload)
+	#
+	# If do_reload() is not implemented then leave this commented out
+	# and leave 'force-reload' as an alias for 'restart'.
+	#
+	#log_daemon_msg "Reloading $DESC" "$NAME"
+	#do_reload
+	#log_end_msg $?
+	#;;
+  restart|force-reload)
+	#
+	# If the "reload" option is implemented then remove the
+	# 'force-reload' alias
+	#
+	log_daemon_msg "Restarting $DESC" "$NAME"
+	do_stop
+	case "$?" in
+	  0|1)
+		do_start
+		case "$?" in
+			0) log_end_msg 0 ;;
+			1) log_end_msg 1 ;; # Old process is still running
+			*) log_end_msg 1 ;; # Failed to start
+		esac
+		;;
+	  *)
+		# Failed to stop
+		log_end_msg 1
+		;;
+	esac
+	;;
+  *)
+	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+	echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
+	exit 3
+	;;
+esac
+
+:
diff --git a/testing/tests/tnc/tnccs-20-fhh/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-fhh/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index b1093d4..0000000
--- a/testing/tests/tnc/tnccs-20-fhh/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,34 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imv 2"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=eap-ttls
-	leftfirewall=yes
-	rightauth=eap-ttls
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
diff --git a/testing/tests/tnc/tnccs-20-fhh/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-fhh/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index 2e277cc..0000000
--- a/testing/tests/tnc/tnccs-20-fhh/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
-
-carol at strongswan.org : EAP "Ar3etTnp"
-dave at strongswan.org  : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-fhh/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-fhh/hosts/moon/etc/strongswan.conf
index 9f3874b..0cd3486 100644
--- a/testing/tests/tnc/tnccs-20-fhh/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-fhh/hosts/moon/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imv = 2
+    }
+  }
   plugins {
     eap-ttls {
       phase2_method = md5
diff --git a/testing/tests/tnc/tnccs-20-fhh/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-fhh/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..1238c1a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-fhh/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,64 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap-carol {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+   eap-dave {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-fhh/posttest.dat b/testing/tests/tnc/tnccs-20-fhh/posttest.dat
index 1865a1c..770cf6e 100644
--- a/testing/tests/tnc/tnccs-20-fhh/posttest.dat
+++ b/testing/tests/tnc/tnccs-20-fhh/posttest.dat
@@ -1,6 +1,6 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-20-fhh/pretest.dat b/testing/tests/tnc/tnccs-20-fhh/pretest.dat
index 39b0e03..f0f6446 100644
--- a/testing/tests/tnc/tnccs-20-fhh/pretest.dat
+++ b/testing/tests/tnc/tnccs-20-fhh/pretest.dat
@@ -6,12 +6,15 @@ carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
 carol::cat /etc/tnc/dummyimc.file
 dave::cat /etc/tnc/dummyimc.file
-moon::cat /etc/tnc/dummyimv.policy
-moon::LOG4CXX_CONFIGURATION=/etc/tnc/log4cxx.properties ipsec start
-carol::LOG4CXX_CONFIGURATION=/etc/tnc/log4cxx.properties ipsec start
-dave::LOG4CXX_CONFIGURATION=/etc/tnc/log4cxx.properties ipsec start
+carol::rm /etc/swanctl/rsa/*
+dave::rm /etc/swanctl/rsa/*
+carol::rm /etc/swanctl/x509/*
+dave::rm /etc/swanctl/x509/*
+moon::service charon start
+carol::service charon start
+dave::service charon start
 moon::expect-connection rw-allow
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/tnc/tnccs-20-fhh/test.conf b/testing/tests/tnc/tnccs-20-fhh/test.conf
index a8a05af..f6db739 100644
--- a/testing/tests/tnc/tnccs-20-fhh/test.conf
+++ b/testing/tests/tnc/tnccs-20-fhh/test.conf
@@ -24,3 +24,6 @@ IPSECHOSTS="moon carol dave"
 #
 RADIUSHOSTS=
 
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/evaltest.dat b/testing/tests/tnc/tnccs-20-hcd-eap/evaltest.dat
index 1293e98..90d1922 100644
--- a/testing/tests/tnc/tnccs-20-hcd-eap/evaltest.dat
+++ b/testing/tests/tnc/tnccs-20-hcd-eap/evaltest.dat
@@ -16,4 +16,3 @@ alice::cat /var/log/daemon.log::policy enforced on peer.*carol at strongswan.org.*i
 alice::cat /var/log/daemon.log::policy enforced on peer.*dave at strongswan.org.*is.*no access::YES
 moon:: cat /var/log/daemon.log::RADIUS authentication of.*dave at strongswan.org.*failed::YES
 moon:: cat /var/log/daemon.log::RADIUS authentication of.*dave at strongswan.org.*failed::YES
-
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/ipsec.conf
deleted file mode 100644
index f2e6119..0000000
--- a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/ipsec.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 2, imv 3"
-
-conn aaa
-	leftcert=aaaCert.pem
-	leftid=aaa.strongswan.org
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/ipsec.secrets
deleted file mode 100644
index 606e184..0000000
--- a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA aaaKey.pem
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/strongswan.conf
index 1ecf6f8..a0db6ae 100644
--- a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/strongswan.conf
@@ -1,8 +1,20 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac socket-default kernel-netlink stroke eap-identity eap-ttls eap-md5 eap-tnc tnc-pdp tnc-imv tnc-tnccs tnccs-20 sqlite
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici socket-default kernel-netlink eap-identity eap-ttls eap-tnc tnc-pdp tnc-imv tnc-tnccs tnccs-20 sqlite
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 2 
+      imv = 3
+    }
+  }
   plugins {
     eap-ttls {
       request_peer_auth = yes
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/ipsec.d/private/aaaKey.pem b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/swanctl/rsa/aaaKey.pem
similarity index 100%
rename from testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/ipsec.d/private/aaaKey.pem
rename to testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/swanctl/rsa/aaaKey.pem
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..e69de29
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/ipsec.d/certs/aaaCert.pem b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/swanctl/x509/aaaCert.pem
similarity index 100%
rename from testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/ipsec.d/certs/aaaCert.pem
rename to testing/tests/tnc/tnccs-20-hcd-eap/hosts/alice/etc/swanctl/x509/aaaCert.pem
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index 2cca42c..0000000
--- a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,24 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 2, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftcert=carolCert.pem
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightsubnet=10.1.0.0/16
-	rightauth=pubkey
-	aaa_identity="C=CH, O=Linux strongSwan, CN=aaa.strongswan.org"
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/carol/etc/strongswan.conf
index 2694b75..f0a6c4b 100644
--- a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/carol/etc/strongswan.conf
@@ -1,8 +1,21 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 2 
+      imc = 3
+    }
+  }
   plugins {
     eap-ttls {
       max_message_count = 0
@@ -17,6 +30,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   os_info {
     name = strongPrint OS
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..db9d4fa
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,27 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap
+         aaa_id = aaa.strongswan.org
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = pubkey 
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 2707b2b..0000000
--- a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,24 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 2, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftauth=eap
-	leftcert=daveCert.pem
-	leftid=dave at strongswan.org
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightsubnet=10.1.0.0/16
-	rightauth=pubkey
-	aaa_identity="C=CH, O=Linux strongSwan, CN=aaa.strongswan.org"
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/dave/etc/strongswan.conf
index dbc845d..f5c3440 100644
--- a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/dave/etc/strongswan.conf
@@ -1,8 +1,21 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 2 
+      imc = 3
+    }
+  }
   plugins {
     eap-ttls {
       max_message_count = 0
@@ -17,6 +30,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   os_info {
     name = strongPrint OS
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..989107a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,27 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap
+         aaa_id = aaa.strongswan.org
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = pubkey 
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index 02ada56..0000000
--- a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,33 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=pubkey
-	leftfirewall=yes
-	rightauth=eap-radius
-	rightsendcert=never
-	right=%any
-	eap_identity=%any
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index e86d6aa..0000000
--- a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/moon/etc/strongswan.conf
index fc647a0..4dae693 100644
--- a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/moon/etc/strongswan.conf
@@ -1,8 +1,13 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-radius updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-radius updown
   multiple_authentication=no
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
   plugins {
     eap-radius {
       secret = gv6URkSs
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..3caad0c
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-hcd-eap/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,53 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey 
+         id = moon.strongswan.org
+         certs = moonCert.pem
+      }
+      remote {
+         auth = eap-radius
+         id = *@strongswan.org
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey 
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-radius
+         id = *@strongswan.org
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/posttest.dat b/testing/tests/tnc/tnccs-20-hcd-eap/posttest.dat
index 369cfe8..bcd6553 100644
--- a/testing/tests/tnc/tnccs-20-hcd-eap/posttest.dat
+++ b/testing/tests/tnc/tnccs-20-hcd-eap/posttest.dat
@@ -1,7 +1,9 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
-alice::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
+alice::service charon stop
+alice::rm /etc/swanctl/rsa/aaaKey.pem
+alice::rm /etc/swanctl/x509/aaaCert.pem
 winnetou::ip route del 10.1.0.0/16 via 192.168.0.1
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/pretest.dat b/testing/tests/tnc/tnccs-20-hcd-eap/pretest.dat
index 0978d12..db8ce10 100644
--- a/testing/tests/tnc/tnccs-20-hcd-eap/pretest.dat
+++ b/testing/tests/tnc/tnccs-20-hcd-eap/pretest.dat
@@ -7,11 +7,13 @@ carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
 carol::echo 0 > /proc/sys/net/ipv4/ip_forward
 dave::echo aabbccddeeff11223344556677889900 > /var/lib/dbus/machine-id
-alice::ipsec start
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+alice::rm /etc/swanctl/rsa/aliceKey.pem
+alice::rm /etc/swanctl/x509/aliceCert.pem
+alice::service charon start
+moon::service charon start
+carol::service charon start
+dave::service charon start
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/tnc/tnccs-20-hcd-eap/test.conf b/testing/tests/tnc/tnccs-20-hcd-eap/test.conf
index c4ca1a1..14b7fc8 100644
--- a/testing/tests/tnc/tnccs-20-hcd-eap/test.conf
+++ b/testing/tests/tnc/tnccs-20-hcd-eap/test.conf
@@ -24,3 +24,6 @@ IPSECHOSTS="moon carol dave alice"
 #
 RADIUSHOSTS=
 
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap-fail/description.txt b/testing/tests/tnc/tnccs-20-mutual-eap-fail/description.txt
new file mode 100644
index 0000000..f910cb5
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-mutual-eap-fail/description.txt
@@ -0,0 +1,5 @@
+The hosts <b>moon</b> and <b>sun</b> do mutual TNC measurements over IKEv2-EAP
+using the PA-TNC, PB-TNC and PT-EAP protocols. The IKEv2 EAP-TTLS authentication
+is based on X.509 certificates. The TNC measurement on <b>moon</b> is successful
+and the measurement on <b>sun</b> fails, causing the IPsec connection to be
+aborted by <b>moon</b>.
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap-fail/evaltest.dat b/testing/tests/tnc/tnccs-20-mutual-eap-fail/evaltest.dat
new file mode 100644
index 0000000..9330322
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-mutual-eap-fail/evaltest.dat
@@ -0,0 +1,7 @@
+moon::cat /var/log/daemon.log::activating mutual PB-TNC half duplex protocol::YES
+sun:: cat /var/log/daemon.log::activating mutual PB-TNC half duplex protocol::YES
+moon::cat /var/log/daemon.log::final recommendation is.*no access::YES
+sun:: cat /var/log/daemon.log::final recommendation is.*allow::YES
+moon::swanctl --list-sas --raw 2> /dev/null::mutual.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-port=500 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*mutual.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.1/32] remote-ts=\[192.168.0.2/32]::NO
+sun::swanctl --list-sas --raw 2> /dev/null::mutual.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=500 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-port=500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*mutual.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.2/32] remote-ts=\[192.168.0.1/32]::NO
+moon::ping -c 1 -W 1 192.168.0.2::64 bytes from 192.168.0.2: icmp_req=1::NO
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/moon/etc/strongswan.conf
new file mode 100644
index 0000000..a555970
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,45 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce x509 openssl pem pkcs1 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-tnc tnc-tnccs tnc-imc tnc-imv tnccs-20 updown
+
+  multiple_authentication = no
+
+ start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 2 
+      imc = 2
+      imv = 2
+    }
+  }
+  plugins {
+    eap-ttls {
+      phase2_tnc = yes
+    }
+    tnccs-20 {
+      mutual = yes
+    }
+  }
+}
+
+libtls {
+  suites = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
+libimcv {
+  plugins {
+    imc-test {
+      command = allow 
+    }
+    imv-test {
+      rounds = 1
+    }   
+  }
+}
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..3290059
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,28 @@
+connections {
+
+   mutual {
+      local_addrs  = 192.168.0.1
+      remote_addrs = 192.168.0.2 
+
+      local {
+         auth = eap-ttls
+         certs = moonCert.pem
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = sun.strongswan.org
+         groups = allow
+      }
+      children {
+         mutual {
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-ecp256
+         }
+      }
+      version = 2
+      mobike = no
+      send_certreq = no
+      proposals = aes128-sha256-ecp256
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/moon/etc/tnc_config b/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/moon/etc/tnc_config
new file mode 100644
index 0000000..476e880
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/moon/etc/tnc_config
@@ -0,0 +1,4 @@
+#IMC/IMV configuration file for strongSwan endpoint 
+
+IMC "Test" /usr/local/lib/ipsec/imcvs/imc-test.so
+IMV "Test" /usr/local/lib/ipsec/imcvs/imv-test.so
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/sun/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/sun/etc/strongswan.conf
new file mode 100644
index 0000000..b2280db
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/sun/etc/strongswan.conf
@@ -0,0 +1,47 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = random nonce x509 openssl pem pkcs1 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-tnc tnc-tnccs tnc-imc tnc-imv tnccs-20 updown
+
+   multiple_authentication = no
+ 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 2 
+      imc = 2
+      imv = 2
+    }
+  }
+  plugins {
+    eap-ttls {
+      request_peer_auth = yes
+      phase2_piggyback = yes
+      phase2_tnc =yes
+    }
+    tnccs-20 {
+      mutual = yes
+    }
+  }
+}
+
+libtls {
+  suites = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
+libimcv {
+  plugins {
+    imc-test {
+      command = none 
+    }
+    imv-test {
+      rounds = 1 
+    }   
+  }
+}
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/sun/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/sun/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..6b559aa
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/sun/etc/swanctl/swanctl.conf
@@ -0,0 +1,28 @@
+connections {
+
+   mutual {
+      local_addrs  = 192.168.0.2
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls 
+         certs = sunCert.pem
+         id = sun.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org
+         groups = allow
+      }
+      children {
+          mutual {
+             updown = /usr/local/libexec/ipsec/_updown iptables
+             esp_proposals = aes128gcm16-ecp256
+          } 
+      }
+      version = 2
+      mobike = no
+      send_certreq = no 
+      proposals = aes128-sha256-ecp256
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/sun/etc/tnc_config b/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/sun/etc/tnc_config
new file mode 100644
index 0000000..476e880
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-mutual-eap-fail/hosts/sun/etc/tnc_config
@@ -0,0 +1,4 @@
+#IMC/IMV configuration file for strongSwan endpoint 
+
+IMC "Test" /usr/local/lib/ipsec/imcvs/imc-test.so
+IMV "Test" /usr/local/lib/ipsec/imcvs/imv-test.so
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap-fail/posttest.dat b/testing/tests/tnc/tnccs-20-mutual-eap-fail/posttest.dat
new file mode 100644
index 0000000..4677e46
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-mutual-eap-fail/posttest.dat
@@ -0,0 +1,4 @@
+moon::service charon stop
+sun::service charon stop
+moon::iptables-restore < /etc/iptables.flush
+sun::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap-fail/pretest.dat b/testing/tests/tnc/tnccs-20-mutual-eap-fail/pretest.dat
new file mode 100644
index 0000000..0a35639
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-mutual-eap-fail/pretest.dat
@@ -0,0 +1,6 @@
+moon::iptables-restore < /etc/iptables.rules
+sun::iptables-restore < /etc/iptables.rules
+moon::service charon start
+sun::service charon start
+moon::expect-connection mutual 
+moon::swanctl --initiate --child mutual 
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap-fail/test.conf b/testing/tests/tnc/tnccs-20-mutual-eap-fail/test.conf
new file mode 100644
index 0000000..5c095ce
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-mutual-eap-fail/test.conf
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# This configuration file provides information on the
+# guest instances used for this test
+
+# All guest instances that are required for this test
+#
+VIRTHOSTS="moon winnetou sun"
+
+# Corresponding block diagram
+#
+DIAGRAM="m-w-s.png"
+ 
+# Guest instances on which tcpdump is to be started
+#
+TCPDUMPHOSTS="sun"
+
+# Guest instances on which IPsec is started
+# Used for IPsec logging purposes
+#
+IPSECHOSTS="moon sun"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap/description.txt b/testing/tests/tnc/tnccs-20-mutual-eap/description.txt
index 6c79b8c..6d5c67a 100644
--- a/testing/tests/tnc/tnccs-20-mutual-eap/description.txt
+++ b/testing/tests/tnc/tnccs-20-mutual-eap/description.txt
@@ -1,3 +1,4 @@
 The hosts <b>moon</b> and <b>sun</b> do mutual TNC measurements over IKEv2-EAP
-using the PA-TNC, PB-TNC and PT-EAP protocols. The authentication is based on
-X.509 certificates.
+using the PA-TNC, PB-TNC and PT-EAP protocols. The IKEv2 EAP-TTLS authentication
+is based on X.509 certificates. The TNC measurements of both <b>moon</b> and
+<b>sun</b> are successful and the IPsec connection gets established.
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap/evaltest.dat b/testing/tests/tnc/tnccs-20-mutual-eap/evaltest.dat
index 0ef7b5d..28f101c 100644
--- a/testing/tests/tnc/tnccs-20-mutual-eap/evaltest.dat
+++ b/testing/tests/tnc/tnccs-20-mutual-eap/evaltest.dat
@@ -1,11 +1,9 @@
 moon::cat /var/log/daemon.log::activating mutual PB-TNC half duplex protocol::YES
 sun:: cat /var/log/daemon.log::activating mutual PB-TNC half duplex protocol::YES
-moon::cat /var/log/daemon.log::PB-TNC access recommendation is.*Access Allowed::YES
-sun:: cat /var/log/daemon.log::PB-TNC access recommendation is.*Access Allowed::YES
-moon::ipsec status 2> /dev/null::host-host.*ESTABLISHED.*moon.strongswan.org.*sun.strongswan.org::YES
-sun:: ipsec status 2> /dev/null::host-host.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES
-moon::ipsec status 2> /dev/null::host-host.*INSTALLED, TUNNEL::YES
-sun:: ipsec status 2> /dev/null::host-host.*INSTALLED, TUNNEL::YES
-moon::ping -c 1 PH_IP_SUN::64 bytes from PH_IP_SUN: icmp_req=1::YES
+moon::cat /var/log/daemon.log::final recommendation is.*allow::YES
+sun:: cat /var/log/daemon.log::final recommendation is.*allow::YES
+moon::swanctl --list-sas --raw 2> /dev/null::mutual.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=500 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-port=500 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*mutual.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.1/32] remote-ts=\[192.168.0.2/32]::YES
+sun::swanctl --list-sas --raw 2> /dev/null::mutual.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-port=500 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-port=500 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*mutual.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.2/32] remote-ts=\[192.168.0.1/32]::YES
+moon::ping -c 1 192.168.0.2::64 bytes from 192.168.0.2: icmp_req=1::YES
 sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
 sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-mutual-eap/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index 47a0283..0000000
--- a/testing/tests/tnc/tnccs-20-mutual-eap/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 2, imc 2, imv 2"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn host-host
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=moon.strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_SUN
-	rightid=sun.strongswan.org
-	rightsendcert=never
-	rightauth=any
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-mutual-eap/hosts/moon/etc/strongswan.conf
index 953e7fc..1212e23 100644
--- a/testing/tests/tnc/tnccs-20-mutual-eap/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-mutual-eap/hosts/moon/etc/strongswan.conf
@@ -1,12 +1,27 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = x509 openssl pem pkcs1 random nonce curl revocation stroke kernel-netlink socket-default eap-identity eap-ttls eap-tnc tnc-tnccs tnc-imc tnc-imv tnccs-20 updown
+  load = random nonce x509 openssl pem pkcs1 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-tnc tnc-tnccs tnc-imc tnc-imv tnccs-20 updown
 
   multiple_authentication = no
+
+ start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 2 
+      imc = 2
+      imv = 2
+    }
+  }
   plugins {
     eap-ttls {
-      phase2_tnc =yes
+      phase2_tnc = yes
     }
     tnccs-20 {
       mutual = yes
@@ -14,6 +29,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-test {
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-mutual-eap/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..3290059
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-mutual-eap/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,28 @@
+connections {
+
+   mutual {
+      local_addrs  = 192.168.0.1
+      remote_addrs = 192.168.0.2 
+
+      local {
+         auth = eap-ttls
+         certs = moonCert.pem
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = sun.strongswan.org
+         groups = allow
+      }
+      children {
+         mutual {
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-ecp256
+         }
+      }
+      version = 2
+      mobike = no
+      send_certreq = no
+      proposals = aes128-sha256-ecp256
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap/hosts/sun/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-mutual-eap/hosts/sun/etc/ipsec.conf
deleted file mode 100644
index c20bce9..0000000
--- a/testing/tests/tnc/tnccs-20-mutual-eap/hosts/sun/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 2, imc 2, imv 2"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn host-host
-	left=PH_IP_SUN
-	leftcert=sunCert.pem
-	leftid=sun.strongswan.org
-	leftauth=eap-ttls
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=moon.strongswan.org
-	rightauth=eap-ttls
-	rightsendcert=never
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap/hosts/sun/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-mutual-eap/hosts/sun/etc/strongswan.conf
index 570126a..f29175d 100644
--- a/testing/tests/tnc/tnccs-20-mutual-eap/hosts/sun/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-mutual-eap/hosts/sun/etc/strongswan.conf
@@ -1,9 +1,24 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = x509 openssl pem pkcs1 random nonce curl revocation stroke kernel-netlink socket-default eap-identity eap-ttls eap-tnc tnc-tnccs tnc-imc tnc-imv tnccs-20 updown
+  load = random nonce x509 openssl pem pkcs1 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-tnc tnc-tnccs tnc-imc tnc-imv tnccs-20 updown
 
-  multiple_authentication = no
+   multiple_authentication = no
+ 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 2 
+      imc = 2
+      imv = 2
+    }
+  }
   plugins {
     eap-ttls {
       request_peer_auth = yes
@@ -16,6 +31,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-test {
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap/hosts/sun/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-mutual-eap/hosts/sun/etc/swanctl/swanctl.conf
new file mode 100755
index 0000000..6b559aa
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-mutual-eap/hosts/sun/etc/swanctl/swanctl.conf
@@ -0,0 +1,28 @@
+connections {
+
+   mutual {
+      local_addrs  = 192.168.0.2
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls 
+         certs = sunCert.pem
+         id = sun.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org
+         groups = allow
+      }
+      children {
+          mutual {
+             updown = /usr/local/libexec/ipsec/_updown iptables
+             esp_proposals = aes128gcm16-ecp256
+          } 
+      }
+      version = 2
+      mobike = no
+      send_certreq = no 
+      proposals = aes128-sha256-ecp256
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap/posttest.dat b/testing/tests/tnc/tnccs-20-mutual-eap/posttest.dat
index 1f7aa73..4677e46 100644
--- a/testing/tests/tnc/tnccs-20-mutual-eap/posttest.dat
+++ b/testing/tests/tnc/tnccs-20-mutual-eap/posttest.dat
@@ -1,4 +1,4 @@
-moon::ipsec stop
-sun::ipsec stop
+moon::service charon stop
+sun::service charon stop
 moon::iptables-restore < /etc/iptables.flush
 sun::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap/pretest.dat b/testing/tests/tnc/tnccs-20-mutual-eap/pretest.dat
index 997a481..0a35639 100644
--- a/testing/tests/tnc/tnccs-20-mutual-eap/pretest.dat
+++ b/testing/tests/tnc/tnccs-20-mutual-eap/pretest.dat
@@ -1,6 +1,6 @@
 moon::iptables-restore < /etc/iptables.rules
 sun::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-sun::ipsec start
-moon::expect-connection host-host
-moon::ipsec up host-host
+moon::service charon start
+sun::service charon start
+moon::expect-connection mutual 
+moon::swanctl --initiate --child mutual 
diff --git a/testing/tests/tnc/tnccs-20-mutual-eap/test.conf b/testing/tests/tnc/tnccs-20-mutual-eap/test.conf
index 55d6e9f..5c095ce 100644
--- a/testing/tests/tnc/tnccs-20-mutual-eap/test.conf
+++ b/testing/tests/tnc/tnccs-20-mutual-eap/test.conf
@@ -19,3 +19,7 @@ TCPDUMPHOSTS="sun"
 # Used for IPsec logging purposes
 #
 IPSECHOSTS="moon sun"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index 98c415e..0000000
--- a/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-/* configuration is read from /etc/pts/options  */
diff --git a/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/moon/etc/pts/options b/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/moon/etc/pts/options
index 79ae1e8..7eea85d 100644
--- a/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/moon/etc/pts/options
+++ b/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/moon/etc/pts/options
@@ -1,8 +1,8 @@
 --connect sun.strongswan.org
 --client moon.strongswan.org
---key /etc/ipsec.d/private/moonKey.pem
---cert /etc/ipsec.d/certs/moonCert.pem
---cert /etc/ipsec.d/cacerts/strongswanCert.pem
+--key /etc/swanctl/rsa/moonKey.pem
+--cert /etc/swanctl/x509/moonCert.pem
+--cert /etc/swanctl/x509ca/strongswanCert.pem
 --mutual
 --quiet
 --debug 2
diff --git a/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/moon/etc/strongswan.conf
index fafdac4..a476878 100644
--- a/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/moon/etc/strongswan.conf
@@ -1,7 +1,11 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 pt-tls-client {
-  load = x509 openssl pem pkcs1 random nonce revocation curl tnc-tnccs tnc-imc tnc-imv tnccs-20 
+  load = random nonce x509 openssl pem pkcs1 revocation curl tnc-tnccs tnc-imc tnc-imv tnccs-20 
+}
+
+libtls {
+  suites = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
 }
 
 libimcv {
diff --git a/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..28da4d4
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# the PT-TLS client reads its configuration and secrets via the command line
diff --git a/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/sun/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/sun/etc/ipsec.conf
deleted file mode 100644
index ba629a2..0000000
--- a/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/sun/etc/ipsec.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 2, imc 2, imv 2"
-
-conn pdp 
-	leftcert=sunCert.pem
-	leftid=sun.strongswan.org
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/sun/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/sun/etc/strongswan.conf
index 05ffdb1..9e694bc 100644
--- a/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/sun/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/sun/etc/strongswan.conf
@@ -1,8 +1,21 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = x509 openssl pem pkcs1 random nonce curl revocation stroke kernel-netlink socket-default tnc-pdp tnc-tnccs tnc-imc tnc-imv tnccs-20 
+  load = random nonce x509 openssl pem pkcs1 revocation curl vici kernel-netlink socket-default tnc-pdp tnc-tnccs tnc-imc tnc-imv tnccs-20 
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 2 
+      imc = 2
+      imv = 2
+    }
+  }
   plugins {
     tnc-pdp {
       server = sun.strongswan.org
@@ -16,6 +29,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-test {
diff --git a/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/sun/etc/swantcl/swanctl.conf b/testing/tests/tnc/tnccs-20-mutual-pt-tls/hosts/sun/etc/swantcl/swanctl.conf
new file mode 100644
index 0000000..e69de29
diff --git a/testing/tests/tnc/tnccs-20-mutual-pt-tls/posttest.dat b/testing/tests/tnc/tnccs-20-mutual-pt-tls/posttest.dat
index e6ccb14..d1f83a3 100644
--- a/testing/tests/tnc/tnccs-20-mutual-pt-tls/posttest.dat
+++ b/testing/tests/tnc/tnccs-20-mutual-pt-tls/posttest.dat
@@ -1 +1 @@
-sun::ipsec stop
+sun::service charon stop
diff --git a/testing/tests/tnc/tnccs-20-mutual-pt-tls/pretest.dat b/testing/tests/tnc/tnccs-20-mutual-pt-tls/pretest.dat
index 07b1760..af53e6c 100644
--- a/testing/tests/tnc/tnccs-20-mutual-pt-tls/pretest.dat
+++ b/testing/tests/tnc/tnccs-20-mutual-pt-tls/pretest.dat
@@ -1,4 +1,4 @@
-sun::ipsec start
+sun::service charon start
 moon::cat /etc/pts/options
-sun::expect-connection pdp
+moon::sleep 1
 moon::ipsec pt-tls-client --optionsfrom /etc/pts/options
diff --git a/testing/tests/tnc/tnccs-20-mutual-pt-tls/test.conf b/testing/tests/tnc/tnccs-20-mutual-pt-tls/test.conf
index 55d6e9f..5c095ce 100644
--- a/testing/tests/tnc/tnccs-20-mutual-pt-tls/test.conf
+++ b/testing/tests/tnc/tnccs-20-mutual-pt-tls/test.conf
@@ -19,3 +19,7 @@ TCPDUMPHOSTS="sun"
 # Used for IPsec logging purposes
 #
 IPSECHOSTS="moon sun"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-20-os-pts/evaltest.dat b/testing/tests/tnc/tnccs-20-os-pts/evaltest.dat
index 8c9e59a..88b55c9 100644
--- a/testing/tests/tnc/tnccs-20-os-pts/evaltest.dat
+++ b/testing/tests/tnc/tnccs-20-os-pts/evaltest.dat
@@ -1,19 +1,19 @@
 carol::cat /var/log/daemon.log::PB-TNC access recommendation is 'Access Allowed'::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/28::YES
 dave:: cat /var/log/daemon.log::PB-TNC access recommendation is 'Quarantined'::YES
 dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.16/28::YES
 moon:: ipsec attest --session 2> /dev/null::Debian.*x86_64.*carol at strongswan.org - allow::YES
 moon:: cat /var/log/daemon.log::added group membership 'allow'::YES
 moon:: cat /var/log/daemon.log::authentication of 'carol at strongswan.org' with EAP successful::YES
 moon:: ipsec attest --session 2> /dev/null::Debian.*x86_64.*dave at strongswan.org - isolate::YES
 moon:: cat /var/log/daemon.log::added group membership 'isolate'::YES
 moon:: cat /var/log/daemon.log::authentication of 'dave at strongswan.org' with EAP successful::YES
-moon:: ipsec statusall 2> /dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.100/32::YES
-moon:: ipsec statusall 2> /dev/null::rw-isolate.*10.1.0.16/28 === 192.168.0.200/32::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.16/ [...]
+moon:: swanctl --list-sas --ike-id 1 --raw  2> /dev/null::rw-allow.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-allow.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/28] remote-ts=\[192.168. [...]
+moon:: swanctl --list-sas --ike-id 2 --raw  2> /dev/null::rw-isolate.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-isolate.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.16/28] remote-ts=\[192. [...]
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
 carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
 dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
diff --git a/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index d17473d..0000000
--- a/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3, pts 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 74942af..0000000
--- a/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol at strongswan.org : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/strongswan.conf
index 0c93429..d3941d8 100644
--- a/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/strongswan.conf
@@ -1,9 +1,28 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = openssl curl pem pkcs1 random nonce revocation stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
+  load = random nonce openssl pem pkcs1 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
 
   multiple_authentication = no
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+      pts = 3
+    }
+  }
+}
+
+libtls {
+  suites = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
 }
 
 libimcv {
diff --git a/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..0f266dd
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index d459bfc..0000000
--- a/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3, pts 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftid=dave at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index 5496df7..0000000
--- a/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-dave at strongswan.org : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/strongswan.conf
index 156a2e4..134cd99 100644
--- a/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/strongswan.conf
@@ -1,12 +1,25 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = openssl curl pem pkcs1 random nonce revocation stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+  load = random nonce openssl pem pkcs1 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
-
   retransmit_tries = 5
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+      pts = 3
+    }
+  }
   plugins {
     tnc-imc {
       preferred_language = de
@@ -14,6 +27,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-os {
diff --git a/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..989ab88
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index bc8b2d8..0000000
--- a/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,34 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imv 3, pts 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=eap-ttls
-	leftfirewall=yes
-	rightauth=eap-ttls
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
diff --git a/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index 2e277cc..0000000
--- a/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
-
-carol at strongswan.org : EAP "Ar3etTnp"
-dave at strongswan.org  : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/strongswan.conf
index c8992bd..4b024e9 100644
--- a/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/strongswan.conf
@@ -1,10 +1,24 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = openssl curl pem pkcs1 random nonce revocation stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown sqlite
+  load = random nonce openssl pem pkcs1 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown sqlite
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imv = 3
+      pts = 3
+    }
+  }
   plugins {
     eap-ttls {
       phase2_method = md5
@@ -14,6 +28,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   database = sqlite:///etc/db.d/config.db
   policy_script = ipsec imv_policy_manager
diff --git a/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..1238c1a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,64 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap-carol {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+   eap-dave {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-os-pts/posttest.dat b/testing/tests/tnc/tnccs-20-os-pts/posttest.dat
index 74b902c..ce72d2c 100644
--- a/testing/tests/tnc/tnccs-20-os-pts/posttest.dat
+++ b/testing/tests/tnc/tnccs-20-os-pts/posttest.dat
@@ -1,6 +1,6 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-20-os-pts/pretest.dat b/testing/tests/tnc/tnccs-20-os-pts/pretest.dat
index 345f548..81537cc 100644
--- a/testing/tests/tnc/tnccs-20-os-pts/pretest.dat
+++ b/testing/tests/tnc/tnccs-20-os-pts/pretest.dat
@@ -8,12 +8,16 @@ moon::cd /usr/local/share/strongswan/templates/database/imv; cat tables.sql data
 moon::cat /etc/tnc_config
 carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
-moon::ipsec start
-dave::ipsec start
-carol::ipsec start
-dave::expect-connection home
-dave::ipsec up home
+carol::rm /etc/swanctl/rsa/*
+dave::rm /etc/swanctl/rsa/*
+carol::rm /etc/swanctl/x509/*
+dave::rm /etc/swanctl/x509/*
+moon::service charon start
+carol::service charon start
+dave::service charon start
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
+dave::swanctl --initiate --child home 2> /dev/null
 moon::ipsec attest --sessions
 moon::ipsec attest --devices
diff --git a/testing/tests/tnc/tnccs-20-os-pts/test.conf b/testing/tests/tnc/tnccs-20-os-pts/test.conf
index 4b1c410..005df9a 100644
--- a/testing/tests/tnc/tnccs-20-os-pts/test.conf
+++ b/testing/tests/tnc/tnccs-20-os-pts/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="moon carol dave"
 # Guest instances on which databases are used
 #
 DBHOSTS="moon"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-20-os/evaltest.dat b/testing/tests/tnc/tnccs-20-os/evaltest.dat
index 2921163..202b408 100644
--- a/testing/tests/tnc/tnccs-20-os/evaltest.dat
+++ b/testing/tests/tnc/tnccs-20-os/evaltest.dat
@@ -1,19 +1,19 @@
 carol::cat /var/log/daemon.log::PB-TNC access recommendation is 'Access Allowed'::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/28::YES
 dave:: cat /var/log/daemon.log::PB-TNC access recommendation is 'Quarantined'::YES
 dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.16/28::YES
 moon:: ipsec attest --sessions 2> /dev/null::Debian.*x86_64.*carol at strongswan.org - allow::YES
 moon:: cat /var/log/daemon.log::added group membership 'allow'::YES
 moon:: cat /var/log/daemon.log::authentication of 'carol at strongswan.org' with EAP successful::YES
 moon:: ipsec attest --sessions 2> /dev/null::Debian.*x86_64.*dave at strongswan.org - isolate::YES
 moon:: cat /var/log/daemon.log::added group membership 'isolate'::YES
 moon:: cat /var/log/daemon.log::authentication of 'dave at strongswan.org' with EAP successful::YES
-moon:: ipsec statusall 2> /dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.100/32::YES
-moon:: ipsec statusall 2> /dev/null::rw-isolate.*10.1.0.16/28 === 192.168.0.200/32::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.16/ [...]
+moon:: swanctl --list-sas --ike-id 1 --raw  2> /dev/null::rw-allow.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-allow.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/28] remote-ts=\[192.168. [...]
+moon:: swanctl --list-sas --ike-id 2 --raw  2> /dev/null::rw-isolate.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-isolate.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.16/28] remote-ts=\[192. [...]
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
 carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
 dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
diff --git a/testing/tests/tnc/tnccs-20-os/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-os/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index e2bf349..0000000
--- a/testing/tests/tnc/tnccs-20-os/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-os/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-os/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 74942af..0000000
--- a/testing/tests/tnc/tnccs-20-os/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol at strongswan.org : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-20-os/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-os/hosts/carol/etc/strongswan.conf
index 0b8e923..ef90078 100644
--- a/testing/tests/tnc/tnccs-20-os/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-os/hosts/carol/etc/strongswan.conf
@@ -1,9 +1,27 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
 
   multiple_authentication = no
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+    }
+  }
+}
+
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
 }
 
 libimcv {
diff --git a/testing/tests/tnc/tnccs-20-os/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-os/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..0f266dd
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-os/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-os/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 77446cb..0000000
--- a/testing/tests/tnc/tnccs-20-os/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftid=dave at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-os/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-os/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index 5496df7..0000000
--- a/testing/tests/tnc/tnccs-20-os/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-dave at strongswan.org : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-os/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-os/hosts/dave/etc/strongswan.conf
index 4dcb5c3..4af05ad 100644
--- a/testing/tests/tnc/tnccs-20-os/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-os/hosts/dave/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+    }
+  }
   plugins {
     tnc-imc {
       preferred_language = de
@@ -12,6 +25,10 @@ charon {
   }
 }
 
+ilibtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-os {
diff --git a/testing/tests/tnc/tnccs-20-os/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-os/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..989ab88
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-os/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-os/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index e21ef0d..0000000
--- a/testing/tests/tnc/tnccs-20-os/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,34 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imv 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=eap-ttls
-	leftfirewall=yes
-	rightauth=eap-ttls
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
diff --git a/testing/tests/tnc/tnccs-20-os/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-os/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index 2e277cc..0000000
--- a/testing/tests/tnc/tnccs-20-os/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
-
-carol at strongswan.org : EAP "Ar3etTnp"
-dave at strongswan.org  : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-os/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-os/hosts/moon/etc/strongswan.conf
index 43cf395..2fae3ba 100644
--- a/testing/tests/tnc/tnccs-20-os/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-os/hosts/moon/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown sqlite
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown sqlite
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imv = 3
+    }
+  }
   plugins {
     eap-ttls {
       phase2_method = md5
@@ -14,6 +27,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   database = sqlite:///etc/db.d/config.db
   policy_script = ipsec imv_policy_manager
diff --git a/testing/tests/tnc/tnccs-20-os/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-os/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..1238c1a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,64 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap-carol {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+   eap-dave {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-os/posttest.dat b/testing/tests/tnc/tnccs-20-os/posttest.dat
index 74b902c..ce72d2c 100644
--- a/testing/tests/tnc/tnccs-20-os/posttest.dat
+++ b/testing/tests/tnc/tnccs-20-os/posttest.dat
@@ -1,6 +1,6 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-20-os/pretest.dat b/testing/tests/tnc/tnccs-20-os/pretest.dat
index 3c5cd32..fa8d089 100644
--- a/testing/tests/tnc/tnccs-20-os/pretest.dat
+++ b/testing/tests/tnc/tnccs-20-os/pretest.dat
@@ -9,13 +9,16 @@ moon::cd /usr/local/share/strongswan/templates/database/imv; cat tables.sql data
 moon::cat /etc/tnc_config
 carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
-carol::sleep 1
-carol::ipsec up home
-dave::ipsec up home
-dave::sleep 1
-moon::ipsec attest --packages --product 'Debian 7.4 x86_64'
+carol::rm /etc/swanctl/rsa/*
+dave::rm /etc/swanctl/rsa/*
+carol::rm /etc/swanctl/x509/*
+dave::rm /etc/swanctl/x509/*
+moon::service charon start
+carol::service charon start
+dave::service charon start
+carol::expect-connection home
+carol::swanctl --initiate --child home 2> /dev/null
+dave::expect-connection home
+dave::swanctl --initiate --child home 2> /dev/nullmoon::ipsec attest --packages --product 'Debian 7.9 x86_64'
 moon::ipsec attest --sessions
 moon::ipsec attest --devices
diff --git a/testing/tests/tnc/tnccs-20-os/test.conf b/testing/tests/tnc/tnccs-20-os/test.conf
index f4fd4dc..005df9a 100644
--- a/testing/tests/tnc/tnccs-20-os/test.conf
+++ b/testing/tests/tnc/tnccs-20-os/test.conf
@@ -22,4 +22,8 @@ IPSECHOSTS="moon carol dave"
 
 # Guest instances on which databases are used
 #
-DBHOSTS="moon"
\ No newline at end of file
+DBHOSTS="moon"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/evaltest.dat b/testing/tests/tnc/tnccs-20-pdp-eap/evaltest.dat
index d373eb3..2d3027c 100644
--- a/testing/tests/tnc/tnccs-20-pdp-eap/evaltest.dat
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/evaltest.dat
@@ -3,14 +3,12 @@ dave:: cat /var/log/daemon.log::PDP server.*aaa.strongswan.org.*is listening on
 dave:: cat /var/log/daemon.log::collected ... SWID tags::YES
 dave:: cat /var/log/daemon.log::PB-TNC access recommendation is .*Quarantined::YES
 dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
-dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.16/28::YES
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA.* successful::YES
 carol::cat /var/log/daemon.log::PDP server.*aaa.strongswan.org.*is listening on port 271::YES
 carol::cat /var/log/daemon.log::collected ... SWID tag IDs::YES
 carol::cat /var/log/daemon.log::collected 1 SWID tag::YES
 carol::cat /var/log/daemon.log::PB-TNC access recommendation is .*Access Allowed::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
-carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/28::YES
 alice::cat /var/log/daemon.log::user AR identity.*dave.*authenticated by password::YES
 alice::cat /var/log/daemon.log::IMV 2 handled SWIDT workitem 3: allow - received inventory of 0 SWID tag IDs and ... SWID tags::YES
 alice::cat /var/log/daemon.log::user AR identity.*carol.*authenticated by password::YES
@@ -21,8 +19,10 @@ moon:: cat /var/log/daemon.log::authentication of '192.168.0.200' with EAP succe
 moon:: cat /var/log/daemon.log::received RADIUS attribute Filter-Id: 'allow'::YES
 moon:: cat /var/log/daemon.log::RADIUS authentication of 'carol' successful::YES
 moon:: cat /var/log/daemon.log::authentication of '192.168.0.100' with EAP successful::YES
-moon:: ipsec statusall 2>/dev/null::rw-isolate.*10.1.0.16/28 === 192.168.0.200/32::YES
-moon:: ipsec statusall 2>/dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.100/32::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=192.168.0.100 remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/28]::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=192.168.0.200 remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.16/28]::YES
+moon:: swanctl --list-sas --ike-id 2 --raw  2> /dev/null::rw-allow.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=192.168.0.100 remote-eap-id=carol.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-allow.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/28] remote- [...]
+moon:: swanctl --list-sas --ike-id 1 --raw  2> /dev/null::rw-isolate.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=192.168.0.200 remote-eap-id=dave.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-isolate.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.16/28] rem [...]
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
 carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
 dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/ipsec.conf
deleted file mode 100644
index f2e6119..0000000
--- a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/ipsec.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 2, imv 3"
-
-conn aaa
-	leftcert=aaaCert.pem
-	leftid=aaa.strongswan.org
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/ipsec.secrets
deleted file mode 100644
index 11d45cd..0000000
--- a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/ipsec.secrets
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA aaaKey.pem
-
-carol : EAP "Ar3etTnp"
-dave  : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/strongswan.conf
index 48d5d70..4328b06 100644
--- a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/strongswan.conf
@@ -1,8 +1,20 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac socket-default kernel-netlink stroke eap-identity eap-ttls eap-md5 eap-tnc tnc-pdp tnc-imv tnc-tnccs tnccs-20 sqlite
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici socket-default kernel-netlink eap-identity eap-ttls eap-md5 eap-tnc tnc-pdp tnc-imv tnc-tnccs tnccs-20 sqlite
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 2 
+      imv = 3
+    }
+  }
   plugins {
     eap-ttls {
       phase2_method = md5
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/ipsec.d/private/aaaKey.pem b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/swanctl/rsa/aaaKey.pem
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/ipsec.d/private/aaaKey.pem
rename to testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/swanctl/rsa/aaaKey.pem
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..378b73a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/swanctl/swanctl.conf
@@ -0,0 +1,11 @@
+secrets {
+
+   eap-carol {
+      id = carol
+      secret = "Ar3etTnp"
+   }
+   eap-dave {
+      id = dave
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/ipsec.d/certs/aaaCert.pem b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/swanctl/x509/aaaCert.pem
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/ipsec.d/certs/aaaCert.pem
rename to testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/swanctl/x509/aaaCert.pem
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index 6e6430e..0000000
--- a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 2, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightsubnet=10.1.0.0/16
-	rightauth=pubkey
-	eap_identity=carol
-	aaa_identity="C=CH, O=Linux strongSwan, CN=aaa.strongswan.org"
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 23d79cf..0000000
--- a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/strongswan.conf
index 8aa2ab9..47b9aff 100644
--- a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/strongswan.conf
@@ -1,10 +1,21 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-
-  retransmit_timeout =
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 2 
+      imc = 3
+    }
+  }
   plugins {
     eap-ttls {
       max_message_count = 0
@@ -18,3 +29,7 @@ charon {
     }
   }
 }
+
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6925f0f
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap
+         eap_id = carol
+         aaa_id = aaa.strongswan.org
+      }
+      remote {
+         auth = pubkey 
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 4846af2..0000000
--- a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 2, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightsubnet=10.1.0.0/16
-	rightauth=pubkey
-	eap_identity=dave
-	aaa_identity="C=CH, O=Linux strongSwan, CN=aaa.strongswan.org"
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index 02e0c99..0000000
--- a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-dave : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/strongswan.conf
index aea7a71..d008083 100644
--- a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/strongswan.conf
@@ -1,10 +1,21 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-
-  retransmit_timeout =
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 2 
+      imc = 3
+    }
+  }
   plugins {
    eap-ttls {
       max_message_count = 0
@@ -19,6 +30,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
    imc-os {
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..0870cf0
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap
+         eap_id = dave
+         aaa_id = aaa.strongswan.org
+      }
+      remote {
+         auth = pubkey 
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = dave
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index 02ada56..0000000
--- a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,33 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=pubkey
-	leftfirewall=yes
-	rightauth=eap-radius
-	rightsendcert=never
-	right=%any
-	eap_identity=%any
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index e86d6aa..0000000
--- a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/strongswan.conf
index fc647a0..8b931af 100644
--- a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/strongswan.conf
@@ -1,8 +1,14 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-radius updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-radius updown
+
   multiple_authentication=no
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
   plugins {
     eap-radius {
       secret = gv6URkSs
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..6ec8d34
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,53 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey 
+         id = moon.strongswan.org
+         certs = moonCert.pem
+      }
+      remote {
+         auth = eap-radius
+         eap_id = %any
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = pubkey 
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-radius
+         eap_id = %any 
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/posttest.dat b/testing/tests/tnc/tnccs-20-pdp-eap/posttest.dat
index fe9f59e..e5ec2af 100644
--- a/testing/tests/tnc/tnccs-20-pdp-eap/posttest.dat
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/posttest.dat
@@ -1,8 +1,10 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
-alice::ipsec stop
+moon::service charon stop
+carol::service charon stop
+dave::service charon stop
+alice::service charon stop
 alice::service apache2 stop
+alice::rm /etc/swanctl/x509/aaaCert.pem
+alice::rm /etc/swanctl/rsa/aaaKey.pem
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/pretest.dat b/testing/tests/tnc/tnccs-20-pdp-eap/pretest.dat
index 4b8d3f0..6292d69 100644
--- a/testing/tests/tnc/tnccs-20-pdp-eap/pretest.dat
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/pretest.dat
@@ -1,6 +1,12 @@
 moon::iptables-restore < /etc/iptables.rules
 carol::iptables-restore < /etc/iptables.rules
 dave::iptables-restore < /etc/iptables.rules
+alice::rm /etc/swanctl/x509/aliceCert.pem
+alice::rm /etc/swanctl/rsa/aliceKey.pem
+carol::rm /etc/swanctl/x509/carolCert.pem
+carol::rm /etc/swanctl/rsa/carolKey.pem
+dave::rm /etc/swanctl/x509/daveCert.pem
+dave::rm /etc/swanctl/rsa/daveKey.pem
 alice::cat /etc/tnc_config
 carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
@@ -12,12 +18,12 @@ alice::cd /usr/local/share/strongswan/templates/database/imv; cat tables.sql dat
 alice::chgrp -R www-data /etc/db.d/config.db; chmod -R g+w /etc/db.d/config.db
 alice::/var/www/tnc/manage.py setpassword strongSwan strongSwan
 alice::service apache2 start
-alice::ipsec start
-moon::ipsec start
-dave::ipsec start
-carol::ipsec start
+alice::service charon start
+moon::service charon start
+dave::service charon start
+carol::service charon start
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 carol::sleep 1
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/test.conf b/testing/tests/tnc/tnccs-20-pdp-eap/test.conf
index 345e911..18522e7 100644
--- a/testing/tests/tnc/tnccs-20-pdp-eap/test.conf
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/test.conf
@@ -24,3 +24,6 @@ IPSECHOSTS="moon carol dave alice"
 #
 DBHOSTS="alice"
 
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.conf
deleted file mode 100644
index 7b2118f..0000000
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tls 2, tnc 2, imv 3"
-
-conn aaa
-	leftcert=aaaCert.pem
-	leftid=aaa.strongswan.org
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.secrets
deleted file mode 100644
index 11d45cd..0000000
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.secrets
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA aaaKey.pem
-
-carol : EAP "Ar3etTnp"
-dave  : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongswan.conf
index 5fa49e7..d1cb6c9 100644
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongswan.conf
@@ -1,8 +1,21 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = pem pkcs1 nonce x509 openssl curl revocation constraints socket-default kernel-netlink stroke tnc-pdp tnc-imv tnc-tnccs tnccs-20 sqlite
+  load = random nonce pem pkcs1 x509 openssl revocation constraints curl vici socket-default kernel-netlink tnc-pdp tnc-imv tnc-tnccs tnccs-20 sqlite
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tls = 2
+      tnc = 2 
+      imv = 3
+    }
+  }
   plugins {
     tnc-pdp {
       server = aaa.strongswan.org
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.d/private/aaaKey.pem b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/swanctl/rsa/aaaKey.pem
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.d/private/aaaKey.pem
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/swanctl/rsa/aaaKey.pem
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..635620b
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/swanctl/swanctl.conf
@@ -0,0 +1,7 @@
+secrets {
+
+   eap-carol {
+      id = carol
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.d/certs/aaaCert.pem b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/swanctl/x509/aaaCert.pem
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.d/certs/aaaCert.pem
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/swanctl/x509/aaaCert.pem
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index 4a41e7e..0000000
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-# the PT-TLS client reads its configuration via the command line
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index d2f6378..0000000
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-# the PT-TLS client loads its secrets via the command line
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/pts/options b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/pts/options
index d485e9b..52a3673 100644
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/pts/options
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/pts/options
@@ -1,6 +1,6 @@
 --connect aaa.strongswan.org
 --client carol
 --secret "Ar3etTnp"
---cert /etc/ipsec.d/cacerts/strongswanCert.pem
+--cert /etc/swanctl/x509ca/strongswanCert.pem
 --quiet
 --debug 2
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..28da4d4
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# the PT-TLS client reads its configuration and secrets via the command line
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 4a41e7e..0000000
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-# the PT-TLS client reads its configuration via the command line
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index d2f6378..0000000
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-# the PT-TLS client loads its secrets via the command line
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/pts/options b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/pts/options
index ca3ca3a..0895314 100644
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/pts/options
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/pts/options
@@ -1,7 +1,7 @@
 --connect aaa.strongswan.org
 --client dave at strongswan.org
---key  /etc/ipsec.d/private/daveKey.pem
---cert /etc/ipsec.d/certs/daveCert.pem
---cert /etc/ipsec.d/cacerts/strongswanCert.pem
+--key  /etc/swanctl/rsa/daveKey.pem
+--cert /etc/swanctl/x509/daveCert.pem
+--cert /etc/swanctl/x509ca/strongswanCert.pem
 --quiet
 --debug 2
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..28da4d4
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# the PT-TLS client reads its configuration and secrets via the command line
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index ecd9d47..0000000
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-# this file is not used in this scenario 
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index 41cf8f8..0000000
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-# this file is not used in this scenario 
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..27f96a6
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1 @@
+# this file is not used in this scenario 
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/posttest.dat b/testing/tests/tnc/tnccs-20-pdp-pt-tls/posttest.dat
index 2f45a14..09c8a6c 100644
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/posttest.dat
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/posttest.dat
@@ -1,8 +1,10 @@
 carol::ip route del 10.1.0.0/16 via 192.168.0.1
 dave::ip route del 10.1.0.0/16 via 192.168.0.1
 winnetou::ip route del 10.1.0.0/16 via 192.168.0.1
-alice::ipsec stop
+alice::service charon stop
 alice::service apache2 stop
+alice::rm /etc/swanctl/rsa/aaaKey.pem
+alice::rm /etc/swanctl/x509/aaaCert.pem
 alice::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/pretest.dat b/testing/tests/tnc/tnccs-20-pdp-pt-tls/pretest.dat
index e14ba89..ea93b2d 100644
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/pretest.dat
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/pretest.dat
@@ -11,8 +11,10 @@ alice::sed -i "s:DEBIAN_VERSION:\`cat /etc/debian_version\`:" /etc/pts/data1.sql
 alice::cd /usr/local/share/strongswan/templates/database/imv; cat tables.sql data.sql /etc/pts/data1.sql | sqlite3 /etc/db.d/config.db
 alice::chgrp -R www-data /etc/db.d/config.db; chmod -R g+w /etc/db.d/config.db
 alice::/var/www/tnc/manage.py setpassword strongSwan strongSwan
+alice::rm /etc/swanctl/x509/aliceCert.pem
+alice::rm /etc/swanctl/rsa/aliceKey.pem
 alice::service apache2 start
-alice::ipsec start
+alice::service charon start
 alice::expect-connection aaa
 winnetou::ip route add 10.1.0.0/16 via 192.168.0.1
 dave::ip route add 10.1.0.0/16 via 192.168.0.1
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/test.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/test.conf
index baeceb9..08ea543 100644
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/test.conf
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/test.conf
@@ -23,3 +23,7 @@ IPSECHOSTS="carol moon dave alice"
 # Guest instances on which databases are used
 #
 DBHOSTS="alice"
+
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/evaltest.dat b/testing/tests/tnc/tnccs-20-pts-no-ecc/evaltest.dat
index 8c9e59a..88b89c9 100644
--- a/testing/tests/tnc/tnccs-20-pts-no-ecc/evaltest.dat
+++ b/testing/tests/tnc/tnccs-20-pts-no-ecc/evaltest.dat
@@ -1,19 +1,19 @@
 carol::cat /var/log/daemon.log::PB-TNC access recommendation is 'Access Allowed'::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/28::YES
 dave:: cat /var/log/daemon.log::PB-TNC access recommendation is 'Quarantined'::YES
 dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.16/28::YES
 moon:: ipsec attest --session 2> /dev/null::Debian.*x86_64.*carol at strongswan.org - allow::YES
 moon:: cat /var/log/daemon.log::added group membership 'allow'::YES
 moon:: cat /var/log/daemon.log::authentication of 'carol at strongswan.org' with EAP successful::YES
 moon:: ipsec attest --session 2> /dev/null::Debian.*x86_64.*dave at strongswan.org - isolate::YES
 moon:: cat /var/log/daemon.log::added group membership 'isolate'::YES
 moon:: cat /var/log/daemon.log::authentication of 'dave at strongswan.org' with EAP successful::YES
-moon:: ipsec statusall 2> /dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.100/32::YES
-moon:: ipsec statusall 2> /dev/null::rw-isolate.*10.1.0.16/28 === 192.168.0.200/32::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.16/ [...]
+moon:: swanctl --list-sas --ike-id 2 --raw  2> /dev/null::rw-allow.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-allow.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/28] remote-ts=\[192.168. [...]
+moon:: swanctl --list-sas --ike-id 1 --raw  2> /dev/null::rw-isolate.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-isolate.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.16/28] remote-ts=\[192. [...]
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
 carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
 dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index d17473d..0000000
--- a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3, pts 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 74942af..0000000
--- a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol at strongswan.org : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/carol/etc/strongswan.conf
index 9f410d1..f4fb7e2 100644
--- a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/carol/etc/strongswan.conf
@@ -1,9 +1,28 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes md5 sha1 sha2 hmac gmp pem pkcs1 random nonce x509 curl revocation stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 gmp hmac pem pkcs1 x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
 
   multiple_authentication = no
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+      pts = 3
+    }
+  }
+}
+
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
 }
 
 libimcv {
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..0f266dd
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index d459bfc..0000000
--- a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3, pts 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftid=dave at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index 5496df7..0000000
--- a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-dave at strongswan.org : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/dave/etc/strongswan.conf
index c69f945..b7a7726 100644
--- a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/dave/etc/strongswan.conf
@@ -1,12 +1,24 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes md5 sha1 sha2 hmac gmp pem pkcs1 random nonce x509 curl revocation stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-
-  retransmit_timeout =
+  load = random nonce aes sha1 sha2 md5 gmp hmac pem pkcs1 x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+      pts = 3
+    }
+  }
   plugins {
     tnc-imc {
       preferred_language = de
@@ -14,6 +26,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-os {
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..989ab88
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index bc8b2d8..0000000
--- a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,34 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imv 3, pts 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=eap-ttls
-	leftfirewall=yes
-	rightauth=eap-ttls
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index 2e277cc..0000000
--- a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
-
-carol at strongswan.org : EAP "Ar3etTnp"
-dave at strongswan.org  : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/moon/etc/strongswan.conf
index 38b2e2e..117ca71 100644
--- a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/moon/etc/strongswan.conf
@@ -1,10 +1,24 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes md5 sha1 sha2 hmac gmp pem pkcs1 random nonce x509 curl revocation stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown sqlite
+  load = random nonce aes sha1 sha2 md5 gmp hmac pem pkcs1 x509 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown sqlite
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imv = 3
+      pts = 3
+    }
+  }
   plugins {
     eap-ttls {
       phase2_method = md5
@@ -14,6 +28,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   database = sqlite:///etc/db.d/config.db
   policy_script = ipsec imv_policy_manager
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..1238c1a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,64 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap-carol {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+   eap-dave {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/posttest.dat b/testing/tests/tnc/tnccs-20-pts-no-ecc/posttest.dat
index 74b902c..ce72d2c 100644
--- a/testing/tests/tnc/tnccs-20-pts-no-ecc/posttest.dat
+++ b/testing/tests/tnc/tnccs-20-pts-no-ecc/posttest.dat
@@ -1,6 +1,6 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/pretest.dat b/testing/tests/tnc/tnccs-20-pts-no-ecc/pretest.dat
index 345f548..4b1c45e 100644
--- a/testing/tests/tnc/tnccs-20-pts-no-ecc/pretest.dat
+++ b/testing/tests/tnc/tnccs-20-pts-no-ecc/pretest.dat
@@ -8,12 +8,16 @@ moon::cd /usr/local/share/strongswan/templates/database/imv; cat tables.sql data
 moon::cat /etc/tnc_config
 carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
-moon::ipsec start
-dave::ipsec start
-carol::ipsec start
+carol::rm /etc/swanctl/rsa/*
+dave::rm /etc/swanctl/rsa/*
+carol::rm /etc/swanctl/x509/*
+dave::rm /etc/swanctl/x509/*
+moon::service charon start
+dave::service charon start
+carol::service charon start
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 moon::ipsec attest --sessions
 moon::ipsec attest --devices
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/test.conf b/testing/tests/tnc/tnccs-20-pts-no-ecc/test.conf
index 2fd3139..005df9a 100644
--- a/testing/tests/tnc/tnccs-20-pts-no-ecc/test.conf
+++ b/testing/tests/tnc/tnccs-20-pts-no-ecc/test.conf
@@ -24,3 +24,6 @@ IPSECHOSTS="moon carol dave"
 #
 DBHOSTS="moon"
 
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-20-pts/evaltest.dat b/testing/tests/tnc/tnccs-20-pts/evaltest.dat
index d677563..a531ddf 100644
--- a/testing/tests/tnc/tnccs-20-pts/evaltest.dat
+++ b/testing/tests/tnc/tnccs-20-pts/evaltest.dat
@@ -1,19 +1,19 @@
 carol::cat /var/log/daemon.log::PB-TNC access recommendation is 'Access Allowed'::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/28::YES
 dave:: cat /var/log/daemon.log::PB-TNC access recommendation is 'Access Allowed'::YES
 dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.0/28::YES
 moon:: ipsec attest --session 2> /dev/null::Debian.*x86_64.*carol at strongswan.org - allow::YES
 moon:: cat /var/log/daemon.log::added group membership 'allow'::YES
 moon:: cat /var/log/daemon.log::authentication of 'carol at strongswan.org' with EAP successful::YES
 moon:: ipsec attest --session 2> /dev/null::Debian.*x86_64.*dave at strongswan.org - allow::YES
 moon:: cat /var/log/daemon.log::added group membership 'allow'::YES
 moon:: cat /var/log/daemon.log::authentication of 'dave at strongswan.org' with EAP successful::YES
-moon:: ipsec statusall 2> /dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.100/32::YES
-moon:: ipsec statusall 2> /dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.200/32::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/28]::YES
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.0/28]::YES
+moon:: swanctl --list-sas --ike-id 2 --raw  2> /dev/null::rw-allow.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*rw-allow.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/28] remote-ts=\[192.168.0. [...]
+moon:: swanctl --list-sas --ike-id 1 --raw  2> /dev/null::rw-allow.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*rw-allow.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/28] remote-ts=\[192.168.0.2 [...]
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
 carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
 dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
diff --git a/testing/tests/tnc/tnccs-20-pts/hosts/carol/etc/.strongswan.conf.swp b/testing/tests/tnc/tnccs-20-pts/hosts/carol/etc/.strongswan.conf.swp
new file mode 100644
index 0000000..f57c1e1
Binary files /dev/null and b/testing/tests/tnc/tnccs-20-pts/hosts/carol/etc/.strongswan.conf.swp differ
diff --git a/testing/tests/tnc/tnccs-20-pts/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pts/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index d17473d..0000000
--- a/testing/tests/tnc/tnccs-20-pts/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3, pts 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-pts/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pts/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 74942af..0000000
--- a/testing/tests/tnc/tnccs-20-pts/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol at strongswan.org : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-20-pts/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pts/hosts/carol/etc/strongswan.conf
index 0c93429..2eb3484 100644
--- a/testing/tests/tnc/tnccs-20-pts/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-pts/hosts/carol/etc/strongswan.conf
@@ -1,9 +1,28 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = openssl curl pem pkcs1 random nonce revocation stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
+  load = random nonce openssl pem pkcs1 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
 
   multiple_authentication = no
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3 
+      imc = 3
+      pts = 3 
+    }
+  }
+}
+
+libtls {
+  suites = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
 }
 
 libimcv {
diff --git a/testing/tests/tnc/tnccs-20-pts/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-pts/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..c35df4f
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pts/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-ecp256
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-ecp256
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-pts/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pts/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index d459bfc..0000000
--- a/testing/tests/tnc/tnccs-20-pts/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3, pts 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftid=dave at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-pts/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pts/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index 5496df7..0000000
--- a/testing/tests/tnc/tnccs-20-pts/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-dave at strongswan.org : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-pts/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pts/hosts/dave/etc/strongswan.conf
index b6c9ab6..e9fa8cb 100644
--- a/testing/tests/tnc/tnccs-20-pts/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-pts/hosts/dave/etc/strongswan.conf
@@ -1,11 +1,24 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = openssl curl pem pkcs1 random nonce revocation stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-
-  retransmit_timeout =
+  load = random nonce openssl pem pkcs1 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+      pts = 3
+    }
+  }
   plugins {
     tnc-imc {
       preferred_language = de
@@ -13,6 +26,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-os {
diff --git a/testing/tests/tnc/tnccs-20-pts/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-pts/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..dd349a0
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pts/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-ecp256
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-ecp256
+   }
+}
+
+secrets {
+
+   eap {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index bc8b2d8..0000000
--- a/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,34 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imv 3, pts 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=eap-ttls
-	leftfirewall=yes
-	rightauth=eap-ttls
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
diff --git a/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index 2e277cc..0000000
--- a/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
-
-carol at strongswan.org : EAP "Ar3etTnp"
-dave at strongswan.org  : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/strongswan.conf
index d9d0624..4b024e9 100644
--- a/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/strongswan.conf
@@ -1,12 +1,24 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = openssl curl pem pkcs1 random nonce revocation stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown sqlite
-
-  retransmit_timeout =
+  load = random nonce openssl pem pkcs1 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown sqlite
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imv = 3
+      pts = 3
+    }
+  }
   plugins {
     eap-ttls {
       phase2_method = md5
@@ -16,6 +28,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   database = sqlite:///etc/db.d/config.db
   policy_script = ipsec imv_policy_manager
diff --git a/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..c7e9b1e
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,64 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-ecp256
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-ecp256
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-ecp256
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-ecp256
+   }
+}
+
+secrets {
+
+   eap-carol {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+   eap-dave {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-pts/posttest.dat b/testing/tests/tnc/tnccs-20-pts/posttest.dat
index 74b902c..ce72d2c 100644
--- a/testing/tests/tnc/tnccs-20-pts/posttest.dat
+++ b/testing/tests/tnc/tnccs-20-pts/posttest.dat
@@ -1,6 +1,6 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-20-pts/pretest.dat b/testing/tests/tnc/tnccs-20-pts/pretest.dat
index 345f548..4b1c45e 100644
--- a/testing/tests/tnc/tnccs-20-pts/pretest.dat
+++ b/testing/tests/tnc/tnccs-20-pts/pretest.dat
@@ -8,12 +8,16 @@ moon::cd /usr/local/share/strongswan/templates/database/imv; cat tables.sql data
 moon::cat /etc/tnc_config
 carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
-moon::ipsec start
-dave::ipsec start
-carol::ipsec start
+carol::rm /etc/swanctl/rsa/*
+dave::rm /etc/swanctl/rsa/*
+carol::rm /etc/swanctl/x509/*
+dave::rm /etc/swanctl/x509/*
+moon::service charon start
+dave::service charon start
+carol::service charon start
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 moon::ipsec attest --sessions
 moon::ipsec attest --devices
diff --git a/testing/tests/tnc/tnccs-20-pts/test.conf b/testing/tests/tnc/tnccs-20-pts/test.conf
index 2fd3139..005df9a 100644
--- a/testing/tests/tnc/tnccs-20-pts/test.conf
+++ b/testing/tests/tnc/tnccs-20-pts/test.conf
@@ -24,3 +24,6 @@ IPSECHOSTS="moon carol dave"
 #
 DBHOSTS="moon"
 
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-20-server-retry/evaltest.dat b/testing/tests/tnc/tnccs-20-server-retry/evaltest.dat
index c69940c..b94dc5e 100644
--- a/testing/tests/tnc/tnccs-20-server-retry/evaltest.dat
+++ b/testing/tests/tnc/tnccs-20-server-retry/evaltest.dat
@@ -1,19 +1,18 @@
 carol::cat /var/log/daemon.log::PB-TNC access recommendation is 'Access Allowed'::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/28::YES
 dave:: cat /var/log/daemon.log::PB-TNC access recommendation is 'Quarantined'::YES
 dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.16/28::YES
 moon:: cat /var/log/daemon.log::added group membership 'allow'::YES
 moon:: cat /var/log/daemon.log::authentication of 'carol at strongswan.org' with EAP successful::YES
 moon:: cat /var/log/daemon.log::added group membership 'isolate'::YES
 moon:: cat /var/log/daemon.log::authentication of 'dave at strongswan.org' with EAP successful::YES
-moon:: ipsec statusall 2> /dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.100/32::YES
-moon:: ipsec statusall 2> /dev/null::rw-isolate.*10.1.0.16/28 === 192.168.0.200/32::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.16/ [...]
+moon:: swanctl --list-sas --ike-id 1 --raw  2> /dev/null::rw-allow.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-allow.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/28] remote-ts=\[192.168. [...]
+moon:: swanctl --list-sas --ike-id 2 --raw  2> /dev/null::rw-isolate.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-isolate.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.16/28] remote-ts=\[192. [...]
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_ALICE: icmp_req=1::NO
+carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
 dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
-dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_VENUS: icmp_req=1::NO
-
+dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
diff --git a/testing/tests/tnc/tnccs-20-server-retry/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-server-retry/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index a483d6d..0000000
--- a/testing/tests/tnc/tnccs-20-server-retry/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 2"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-server-retry/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-server-retry/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 74942af..0000000
--- a/testing/tests/tnc/tnccs-20-server-retry/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol at strongswan.org : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-20-server-retry/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-server-retry/hosts/carol/etc/strongswan.conf
index 85287fb..7e51900 100644
--- a/testing/tests/tnc/tnccs-20-server-retry/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-server-retry/hosts/carol/etc/strongswan.conf
@@ -1,9 +1,27 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 2 
+    }
+  }
+}
+
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
 }
 
 libimcv {
diff --git a/testing/tests/tnc/tnccs-20-server-retry/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-server-retry/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..0f266dd
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-server-retry/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-server-retry/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-server-retry/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 1137813..0000000
--- a/testing/tests/tnc/tnccs-20-server-retry/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 2"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftid=dave at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-server-retry/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-server-retry/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index 5496df7..0000000
--- a/testing/tests/tnc/tnccs-20-server-retry/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-dave at strongswan.org : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-server-retry/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-server-retry/hosts/dave/etc/strongswan.conf
index f068d12..4aeda66 100644
--- a/testing/tests/tnc/tnccs-20-server-retry/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-server-retry/hosts/dave/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 2 
+    }
+  }
   plugins {
     tnc-imc {
       preferred_language = ru , de, en
@@ -12,6 +25,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-test {
diff --git a/testing/tests/tnc/tnccs-20-server-retry/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-server-retry/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..989ab88
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-server-retry/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-server-retry/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-server-retry/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index b1093d4..0000000
--- a/testing/tests/tnc/tnccs-20-server-retry/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,34 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imv 2"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=eap-ttls
-	leftfirewall=yes
-	rightauth=eap-ttls
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
diff --git a/testing/tests/tnc/tnccs-20-server-retry/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-server-retry/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index 2e277cc..0000000
--- a/testing/tests/tnc/tnccs-20-server-retry/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
-
-carol at strongswan.org : EAP "Ar3etTnp"
-dave at strongswan.org  : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-server-retry/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-server-retry/hosts/moon/etc/strongswan.conf
index 009e2ef..902e837 100644
--- a/testing/tests/tnc/tnccs-20-server-retry/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-server-retry/hosts/moon/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-20 tnc-imv updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-20 tnc-imv updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imv = 2 
+    }
+  }
   plugins {
     eap-ttls {
       phase2_method = md5
@@ -14,6 +27,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imv-test {
diff --git a/testing/tests/tnc/tnccs-20-server-retry/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-server-retry/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..1238c1a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-server-retry/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,64 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap-carol {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+   eap-dave {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-server-retry/posttest.dat b/testing/tests/tnc/tnccs-20-server-retry/posttest.dat
index 1865a1c..770cf6e 100644
--- a/testing/tests/tnc/tnccs-20-server-retry/posttest.dat
+++ b/testing/tests/tnc/tnccs-20-server-retry/posttest.dat
@@ -1,6 +1,6 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-20-server-retry/pretest.dat b/testing/tests/tnc/tnccs-20-server-retry/pretest.dat
index 8562203..c8ab143 100644
--- a/testing/tests/tnc/tnccs-20-server-retry/pretest.dat
+++ b/testing/tests/tnc/tnccs-20-server-retry/pretest.dat
@@ -4,10 +4,14 @@ dave::iptables-restore < /etc/iptables.rules
 moon::cat /etc/tnc_config
 carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+carol::rm /etc/swanctl/rsa/*
+dave::rm /etc/swanctl/rsa/*
+carol::rm /etc/swanctl/x509/*
+dave::rm /etc/swanctl/x509/*
+moon::service charon start
+carol::service charon start
+dave::service charon start
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/tnc/tnccs-20-server-retry/test.conf b/testing/tests/tnc/tnccs-20-server-retry/test.conf
index a8a05af..f6db739 100644
--- a/testing/tests/tnc/tnccs-20-server-retry/test.conf
+++ b/testing/tests/tnc/tnccs-20-server-retry/test.conf
@@ -24,3 +24,6 @@ IPSECHOSTS="moon carol dave"
 #
 RADIUSHOSTS=
 
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-20-tls/evaltest.dat b/testing/tests/tnc/tnccs-20-tls/evaltest.dat
index fe1becb..ff9ac28 100644
--- a/testing/tests/tnc/tnccs-20-tls/evaltest.dat
+++ b/testing/tests/tnc/tnccs-20-tls/evaltest.dat
@@ -1,19 +1,18 @@
 carol::cat /var/log/daemon.log::PB-TNC access recommendation is 'Access Allowed'::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/28::YES
 dave:: cat /var/log/daemon.log::PB-TNC access recommendation is 'Quarantined'::YES
 dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.16/28::YES
 moon:: cat /var/log/daemon.log::added group membership 'allow'::YES
 moon:: cat /var/log/daemon.log::authentication of 'C=CH, O=Linux strongSwan, OU=Research, CN=carol at strongswan.org' with EAP successful::YES
 moon:: cat /var/log/daemon.log::added group membership 'isolate'::YES
 moon:: cat /var/log/daemon.log::authentication of 'C=CH, O=Linux strongSwan, OU=Accounting, CN=dave at strongswan.org' with EAP successful::YES
-moon:: ipsec statusall 2> /dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.100/32::YES
-moon:: ipsec statusall 2> /dev/null::rw-isolate.*10.1.0.16/28 === 192.168.0.200/32::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=C=CH, O=Linux strongSwan, OU=Research, CN=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=C=CH, O=Linux strongSwan, OU=Accounting, CN=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-t [...]
+moon:: swanctl --list-sas --ike-id 1 --raw  2> /dev/null::rw-allow.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=C=CH, O=Linux strongSwan, OU=Research, CN=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-allow.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*lo [...]
+moon:: swanctl --list-sas --ike-id 2 --raw  2> /dev/null::rw-isolate.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=C=CH, O=Linux strongSwan, OU=Accounting, CN=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-isolate.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=12 [...]
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_ALICE: icmp_req=1::NO
+carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
 dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
-dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_VENUS: icmp_req=1::NO
-
+dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
diff --git a/testing/tests/tnc/tnccs-20-tls/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-tls/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index eece9f2..0000000
--- a/testing/tests/tnc/tnccs-20-tls/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 2, imc 2"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftcert=carolCert.pem
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-tls/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-tls/hosts/carol/etc/strongswan.conf
index 6c7ef55..73f3242 100644
--- a/testing/tests/tnc/tnccs-20-tls/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-tls/hosts/carol/etc/strongswan.conf
@@ -1,9 +1,27 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 2 
+      imc = 2
+    }
+  }
+}
+
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
 }
 
 libimcv {
diff --git a/testing/tests/tnc/tnccs-20-tls/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-tls/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..7898275
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-tls/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,27 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         certs = carolCert.pem 
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-tls/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-tls/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 3620426..0000000
--- a/testing/tests/tnc/tnccs-20-tls/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 2, imc 2"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftcert=daveCert.pem
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-tls/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-tls/hosts/dave/etc/strongswan.conf
index 67c3007..07df4c0 100644
--- a/testing/tests/tnc/tnccs-20-tls/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-tls/hosts/dave/etc/strongswan.conf
@@ -1,9 +1,27 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 2 
+      imc = 2
+    }
+  }
+}
+
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
 }
 
 libimcv {
diff --git a/testing/tests/tnc/tnccs-20-tls/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-tls/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..73c379c
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-tls/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,27 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         certs =daveCert.pem
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-tls/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-tls/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index 0ec9302..0000000
--- a/testing/tests/tnc/tnccs-20-tls/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,34 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 2, imv 2"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=eap-ttls
-	leftfirewall=yes
-	rightauth=eap-ttls
-	rightid="C=CH, O=Linux strongSwan, OU=*, CN=*"
-	rightsendcert=never
-	right=%any
diff --git a/testing/tests/tnc/tnccs-20-tls/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-tls/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index 2e277cc..0000000
--- a/testing/tests/tnc/tnccs-20-tls/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
-
-carol at strongswan.org : EAP "Ar3etTnp"
-dave at strongswan.org  : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20-tls/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-tls/hosts/moon/etc/strongswan.conf
index a408b73..7aef92f 100644
--- a/testing/tests/tnc/tnccs-20-tls/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-tls/hosts/moon/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-20 tnc-imv updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnccs-20 tnc-imv updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 2 
+      imv = 2
+    }
+  }
   plugins {
     eap-ttls {
       request_peer_auth = yes
@@ -13,3 +26,7 @@ charon {
     }
   }
 }
+
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
diff --git a/testing/tests/tnc/tnccs-20-tls/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20-tls/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..99ef2c9
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-tls/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,50 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20-tls/posttest.dat b/testing/tests/tnc/tnccs-20-tls/posttest.dat
index 1865a1c..770cf6e 100644
--- a/testing/tests/tnc/tnccs-20-tls/posttest.dat
+++ b/testing/tests/tnc/tnccs-20-tls/posttest.dat
@@ -1,6 +1,6 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-20-tls/pretest.dat b/testing/tests/tnc/tnccs-20-tls/pretest.dat
index 8562203..709a771 100644
--- a/testing/tests/tnc/tnccs-20-tls/pretest.dat
+++ b/testing/tests/tnc/tnccs-20-tls/pretest.dat
@@ -4,10 +4,10 @@ dave::iptables-restore < /etc/iptables.rules
 moon::cat /etc/tnc_config
 carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+moon::service charon start
+carol::service charon start
+dave::service charon start
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/tnc/tnccs-20-tls/test.conf b/testing/tests/tnc/tnccs-20-tls/test.conf
index a8a05af..f6db739 100644
--- a/testing/tests/tnc/tnccs-20-tls/test.conf
+++ b/testing/tests/tnc/tnccs-20-tls/test.conf
@@ -24,3 +24,6 @@ IPSECHOSTS="moon carol dave"
 #
 RADIUSHOSTS=
 
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-20/evaltest.dat b/testing/tests/tnc/tnccs-20/evaltest.dat
index c69940c..b94dc5e 100644
--- a/testing/tests/tnc/tnccs-20/evaltest.dat
+++ b/testing/tests/tnc/tnccs-20/evaltest.dat
@@ -1,19 +1,18 @@
 carol::cat /var/log/daemon.log::PB-TNC access recommendation is 'Access Allowed'::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/28::YES
 dave:: cat /var/log/daemon.log::PB-TNC access recommendation is 'Quarantined'::YES
 dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.16/28::YES
 moon:: cat /var/log/daemon.log::added group membership 'allow'::YES
 moon:: cat /var/log/daemon.log::authentication of 'carol at strongswan.org' with EAP successful::YES
 moon:: cat /var/log/daemon.log::added group membership 'isolate'::YES
 moon:: cat /var/log/daemon.log::authentication of 'dave at strongswan.org' with EAP successful::YES
-moon:: ipsec statusall 2> /dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.100/32::YES
-moon:: ipsec statusall 2> /dev/null::rw-isolate.*10.1.0.16/28 === 192.168.0.200/32::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.16/ [...]
+moon:: swanctl --list-sas --ike-id 1 --raw  2> /dev/null::rw-allow.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-allow.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/28] remote-ts=\[192.168. [...]
+moon:: swanctl --list-sas --ike-id 2 --raw  2> /dev/null::rw-isolate.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-isolate.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.16/28] remote-ts=\[192. [...]
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_ALICE: icmp_req=1::NO
+carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
 dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
-dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_VENUS: icmp_req=1::NO
-
+dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
diff --git a/testing/tests/tnc/tnccs-20/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index e2bf349..0000000
--- a/testing/tests/tnc/tnccs-20/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 74942af..0000000
--- a/testing/tests/tnc/tnccs-20/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol at strongswan.org : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-20/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-20/hosts/carol/etc/strongswan.conf
index c1693c1..8878064 100644
--- a/testing/tests/tnc/tnccs-20/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20/hosts/carol/etc/strongswan.conf
@@ -1,9 +1,27 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
 
   multiple_authentication = no
+
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+    }
+  }
+}
+
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
 }
 
 libimcv {
diff --git a/testing/tests/tnc/tnccs-20/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..0f266dd
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 77446cb..0000000
--- a/testing/tests/tnc/tnccs-20/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftid=dave at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index 5496df7..0000000
--- a/testing/tests/tnc/tnccs-20/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-dave at strongswan.org : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-20/hosts/dave/etc/strongswan.conf
index d8026b2..e78272b 100644
--- a/testing/tests/tnc/tnccs-20/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20/hosts/dave/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+    }
+  }
   plugins {
     tnc-imc {
       preferred_language = ru, pl  , de
@@ -12,6 +25,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-test {
diff --git a/testing/tests/tnc/tnccs-20/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..989ab88
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index e21ef0d..0000000
--- a/testing/tests/tnc/tnccs-20/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,34 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imv 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=eap-ttls
-	leftfirewall=yes
-	rightauth=eap-ttls
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
diff --git a/testing/tests/tnc/tnccs-20/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index 2e277cc..0000000
--- a/testing/tests/tnc/tnccs-20/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
-
-carol at strongswan.org : EAP "Ar3etTnp"
-dave at strongswan.org  : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-20/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20/hosts/moon/etc/strongswan.conf
index 9c13fcb..165c5cc 100644
--- a/testing/tests/tnc/tnccs-20/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20/hosts/moon/etc/strongswan.conf
@@ -1,10 +1,23 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown
 
   multiple_authentication = no
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imv = 3
+    }
+  }
   plugins {
     eap-ttls {
       phase2_method = md5
@@ -14,6 +27,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imv-test {
diff --git a/testing/tests/tnc/tnccs-20/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-20/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..1238c1a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,64 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap-carol {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+   eap-dave {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-20/posttest.dat b/testing/tests/tnc/tnccs-20/posttest.dat
index 1865a1c..770cf6e 100644
--- a/testing/tests/tnc/tnccs-20/posttest.dat
+++ b/testing/tests/tnc/tnccs-20/posttest.dat
@@ -1,6 +1,6 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-20/pretest.dat b/testing/tests/tnc/tnccs-20/pretest.dat
index 8562203..c8ab143 100644
--- a/testing/tests/tnc/tnccs-20/pretest.dat
+++ b/testing/tests/tnc/tnccs-20/pretest.dat
@@ -4,10 +4,14 @@ dave::iptables-restore < /etc/iptables.rules
 moon::cat /etc/tnc_config
 carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
+carol::rm /etc/swanctl/rsa/*
+dave::rm /etc/swanctl/rsa/*
+carol::rm /etc/swanctl/x509/*
+dave::rm /etc/swanctl/x509/*
+moon::service charon start
+carol::service charon start
+dave::service charon start
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/tnc/tnccs-20/test.conf b/testing/tests/tnc/tnccs-20/test.conf
index a8a05af..f6db739 100644
--- a/testing/tests/tnc/tnccs-20/test.conf
+++ b/testing/tests/tnc/tnccs-20/test.conf
@@ -24,3 +24,6 @@ IPSECHOSTS="moon carol dave"
 #
 RADIUSHOSTS=
 
+# charon controlled by swanctl
+#
+SWANCTL=1
diff --git a/testing/tests/tnc/tnccs-dynamic/evaltest.dat b/testing/tests/tnc/tnccs-dynamic/evaltest.dat
index 3d0c554..2bb1254 100644
--- a/testing/tests/tnc/tnccs-dynamic/evaltest.dat
+++ b/testing/tests/tnc/tnccs-dynamic/evaltest.dat
@@ -1,11 +1,9 @@
 carol::cat /var/log/daemon.log::TNCCS-Recommendation.*allow::YES
 carol::cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-carol::cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.100/32 === 10.1.0.0/28::YES
 dave:: cat /var/log/daemon.log::PB-TNC access recommendation is 'Quarantined'::YES
 dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES
 dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES
-dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.16/28::YES
 moon:: cat /var/log/daemon.log::TNCCS 1.1 protocol detected dynamically::YES
 moon:: cat /var/log/daemon.log::assigned TNCCS Connection ID 1::YES
 moon:: cat /var/log/daemon.log::final recommendation is 'allow' and evaluation is 'compliant'::YES
@@ -18,10 +16,11 @@ moon:: cat /var/log/daemon.log::final recommendation is 'isolate' and evaluation
 moon:: cat /var/log/daemon.log::added group membership 'isolate'::YES
 moon:: cat /var/log/daemon.log::authentication of 'dave at strongswan.org' with EAP successful::YES
 moon:: cat /var/log/daemon.log::removed TNCCS Connection ID 2::YES
-moon:: ipsec statusall 2> /dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.100/32::YES
-moon:: ipsec statusall 2> /dev/null::rw-isolate.*10.1.0.16/28 === 192.168.0.200/32::YES
+carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/ [...]
+dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave at strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.16/ [...]
+moon:: swanctl --list-sas --ike-id 1 --raw  2> /dev/null::rw-allow.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-allow.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/28] remote-ts=\[192.168. [...]
+moon:: swanctl --list-sas --ike-id 2 --raw  2> /dev/null::rw-isolate.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave at strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*rw-isolate.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.16/28] remote-ts=\[192. [...]
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_ALICE: icmp_req=1::NO
+carol::ping -c 1 -W 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
 dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
-dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_VENUS: icmp_req=1::NO
-
+dave:: ping -c 1 -W 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
diff --git a/testing/tests/tnc/tnccs-dynamic/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-dynamic/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index e2bf349..0000000
--- a/testing/tests/tnc/tnccs-dynamic/hosts/carol/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_CAROL
-	leftid=carol at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-dynamic/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-dynamic/hosts/carol/etc/ipsec.secrets
deleted file mode 100644
index 74942af..0000000
--- a/testing/tests/tnc/tnccs-dynamic/hosts/carol/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-carol at strongswan.org : EAP "Ar3etTnp"
diff --git a/testing/tests/tnc/tnccs-dynamic/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-dynamic/hosts/carol/etc/strongswan.conf
index a81460b..609852b 100644
--- a/testing/tests/tnc/tnccs-dynamic/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-dynamic/hosts/carol/etc/strongswan.conf
@@ -1,11 +1,24 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-11 updown
 
   multiple_authentication=no
   integrity_test = yes
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+    }
+  }
   plugins {
     eap-tnc {
       protocol = tnccs-1.1
@@ -13,6 +26,10 @@ charon {
   }
 }
 
+ilibtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-test {
diff --git a/testing/tests/tnc/tnccs-dynamic/hosts/carol/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-dynamic/hosts/carol/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..0f266dd
--- /dev/null
+++ b/testing/tests/tnc/tnccs-dynamic/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-dynamic/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-dynamic/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 77446cb..0000000
--- a/testing/tests/tnc/tnccs-dynamic/hosts/dave/etc/ipsec.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imc 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn home
-	left=PH_IP_DAVE
-	leftid=dave at strongswan.org
-	leftauth=eap
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightauth=any
-	rightsendcert=never
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/tnc/tnccs-dynamic/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-dynamic/hosts/dave/etc/ipsec.secrets
deleted file mode 100644
index 5496df7..0000000
--- a/testing/tests/tnc/tnccs-dynamic/hosts/dave/etc/ipsec.secrets
+++ /dev/null
@@ -1,3 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-dave at strongswan.org : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-dynamic/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-dynamic/hosts/dave/etc/strongswan.conf
index b64aeeb..2c0deca 100644
--- a/testing/tests/tnc/tnccs-dynamic/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-dynamic/hosts/dave/etc/strongswan.conf
@@ -1,11 +1,24 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
 
   multiple_authentication=no
   integrity_test = yes
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imc = 3
+    }
+  }
   plugins {
     eap-tnc {
       protocol = tnccs-2.0
@@ -13,6 +26,10 @@ charon {
   }
 }
 
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
 libimcv {
   plugins {
     imc-test {
diff --git a/testing/tests/tnc/tnccs-dynamic/hosts/dave/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-dynamic/hosts/dave/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..989ab88
--- /dev/null
+++ b/testing/tests/tnc/tnccs-dynamic/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,35 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = eap-ttls
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = moon.strongswan.org 
+      }
+      children {
+         home {
+            remote_ts = 10.1.0.0/16 
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-dynamic/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-dynamic/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index e21ef0d..0000000
--- a/testing/tests/tnc/tnccs-dynamic/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,34 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imv 3"
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-
-conn rw-allow
-	rightgroups=allow
-	leftsubnet=10.1.0.0/28
-	also=rw-eap
-	auto=add
-
-conn rw-isolate
-	rightgroups=isolate
-	leftsubnet=10.1.0.16/28
-	also=rw-eap
-	auto=add
-
-conn rw-eap
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftauth=eap-ttls
-	leftfirewall=yes
-	rightauth=eap-ttls
-	rightid=*@strongswan.org
-	rightsendcert=never
-	right=%any
diff --git a/testing/tests/tnc/tnccs-dynamic/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-dynamic/hosts/moon/etc/ipsec.secrets
deleted file mode 100644
index 2e277cc..0000000
--- a/testing/tests/tnc/tnccs-dynamic/hosts/moon/etc/ipsec.secrets
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/ipsec.secrets - strongSwan IPsec secrets file
-
-: RSA moonKey.pem
-
-carol at strongswan.org : EAP "Ar3etTnp"
-dave at strongswan.org  : EAP "W7R0g3do"
diff --git a/testing/tests/tnc/tnccs-dynamic/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-dynamic/hosts/moon/etc/strongswan.conf
index 45c132f..d61bcd1 100644
--- a/testing/tests/tnc/tnccs-dynamic/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-dynamic/hosts/moon/etc/strongswan.conf
@@ -1,11 +1,24 @@
 # /etc/strongswan.conf - strongSwan configuration file
 
 charon {
-  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-dynamic tnccs-11 tnccs-20 tnc-imv updown
+  load = random nonce aes sha1 sha2 md5 pem pkcs1 gmp hmac x509 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-dynamic tnccs-11 tnccs-20 tnc-imv updown
 
   multiple_authentication=no
   integrity_test = yes
 
+  start-scripts {
+    creds = /usr/local/sbin/swanctl --load-creds 
+    conns = /usr/local/sbin/swanctl --load-conns
+  }
+  syslog {
+    auth {
+      default = 0
+    }
+    daemon {
+      tnc = 3
+      imv = 3
+    }
+  }
   plugins {
     eap-ttls {
       phase2_method = md5
@@ -18,3 +31,8 @@ charon {
     }
   }
 }
+
+libtls {
+  suites = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+}
+
diff --git a/testing/tests/tnc/tnccs-dynamic/hosts/moon/etc/swanctl/swanctl.conf b/testing/tests/tnc/tnccs-dynamic/hosts/moon/etc/swanctl/swanctl.conf
new file mode 100644
index 0000000..1238c1a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-dynamic/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,64 @@
+connections {
+
+   rw-allow {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = allow
+      }
+      children {
+         rw-allow {
+            local_ts = 10.1.0.0/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+
+   rw-isolate {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = eap-ttls
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = eap-ttls
+         id = *@strongswan.org
+         groups = isolate
+      }
+      children {
+         rw-isolate {
+            local_ts = 10.1.0.16/28
+
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            esp_proposals = aes128gcm16-modp3072
+         }
+      }
+      version = 2
+      send_certreq = no
+      proposals = aes128-sha256-modp3072
+   }
+}
+
+secrets {
+
+   eap-carol {
+      id = carol at strongswan.org
+      secret = "Ar3etTnp"
+   }
+   eap-dave {
+      id = dave at strongswan.org
+      secret = "W7R0g3do"
+   }
+}
diff --git a/testing/tests/tnc/tnccs-dynamic/posttest.dat b/testing/tests/tnc/tnccs-dynamic/posttest.dat
index 1865a1c..770cf6e 100644
--- a/testing/tests/tnc/tnccs-dynamic/posttest.dat
+++ b/testing/tests/tnc/tnccs-dynamic/posttest.dat
@@ -1,6 +1,6 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
+carol::service charon stop
+dave::service charon stop
+moon::service charon stop
 moon::iptables-restore < /etc/iptables.flush
 carol::iptables-restore < /etc/iptables.flush
 dave::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/tnc/tnccs-dynamic/pretest.dat b/testing/tests/tnc/tnccs-dynamic/pretest.dat
index 927b89d..c8ab143 100644
--- a/testing/tests/tnc/tnccs-dynamic/pretest.dat
+++ b/testing/tests/tnc/tnccs-dynamic/pretest.dat
@@ -4,10 +4,14 @@ dave::iptables-restore < /etc/iptables.rules
 moon::cat /etc/tnc_config
 carol::cat /etc/tnc_config
 dave::cat /etc/tnc_config
-moon::LEAK_DETECTIVE_DISABLE=1 ipsec start
-carol::LEAK_DETECTIVE_DISABLE=1 ipsec start
-dave::ipsec start
+carol::rm /etc/swanctl/rsa/*
+dave::rm /etc/swanctl/rsa/*
+carol::rm /etc/swanctl/x509/*
+dave::rm /etc/swanctl/x509/*
+moon::service charon start
+carol::service charon start
+dave::service charon start
 carol::expect-connection home
-carol::ipsec up home
+carol::swanctl --initiate --child home 2> /dev/null
 dave::expect-connection home
-dave::ipsec up home
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/tnc/tnccs-dynamic/test.conf b/testing/tests/tnc/tnccs-dynamic/test.conf
index a8a05af..f6db739 100644
--- a/testing/tests/tnc/tnccs-dynamic/test.conf
+++ b/testing/tests/tnc/tnccs-dynamic/test.conf
@@ -24,3 +24,6 @@ IPSECHOSTS="moon carol dave"
 #
 RADIUSHOSTS=
 
+# charon controlled by swanctl
+#
+SWANCTL=1

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-swan/strongswan.git



More information about the Pkg-swan-devel mailing list